Avatar billede hrc Mester
24. april 2012 - 13:55 Der er 6 kommentarer og
2 løsninger

Fejl ved luk af klientdatasæt

Mit program har en form der indeholder en journal. Forbindelsen til denne sker via et TClientDataSet som hænger på en provider og en TADOQuery. Det meste af indholdet i formen er konfigurerbart og oprettes "on-the-fly". Der oprettes frames, sendes beskedder rundt til dem osv. Der sker en hel del.

Datasættet ligger på et TDataModule der oprettes i formens constructor og frigives i dens destructor. Altså egentlig lige ud ad landevejen.

... men jeg får en fejl når jeg forsøger at frigive DataModulet via formens OnDestroy (har også prøvet OnClose).

For at føje mere mystik til så sker det kun hvis programmet har åbnet et eksternt program, eksempelvis Adobe Reader - måske noget med OnExit på de byggeklodser der er oprettet i formen, men ingen af disse frigiver noget.

... nå men. Jeg kan spore fejlen så langt som til frigivelsen af et interface i DBClient:

procedure TCustomClientDataSet.CloseCursor;
var
  Params: OleVariant;
  RecsOut: Integer;
  Options: TGetRecordOptions;
  ChangesMade: LongBool;
begin
  ChangesMade := True;
  if Assigned(FDSBase) then
    FDSBase.GetProp(dspropDATAHASCHANGED, @ChangesMade);
  if (FileName <> '') and not (csDesigning in ComponentState) and
    (ChangesMade or not(FileExists(FileName))) then
    SaveToFile(FileName);
  inherited CloseCursor;
  if HasAppServer then
  begin
    if not (csDestroying in ComponentState) then
    begin
      if FMasterLink.Active and (FMasterLink.Fields.Count > 0) and
        (PacketRecords = 0) then
        Params := Null else
        Params := Unassigned;
      if not (doNoResetCall in FDSOptions) then
      begin
        Options := [grReset];
        DoGetRecords(0, RecsOut, Byte(Options), '', Unassigned);
      end;
      FAppServer := nil;
    end;
  end
  else if FSavePacketOnClose and (FileName = '') and (ProviderName = '') and
    (FParentDataSet = nil) then
    SaveDataPacket;
  FDSBase := nil; Det er her det går galt
  FCloneSource := nil;
  FParentDataSet := nil;
  SetAltRecBuffers(nil, nil, nil);
end;

Der er to varianter af programmet og de giver konsekvent en null pointer assignment

Er der nogen der kan hjælpe mig videre?
Avatar billede mbsnet Nybegynder
24. april 2012 - 14:42 #1
Hej hrc. det kan være "ejeren" af FDSBase som allerede er frigjort.
Altså "TCustomClientDataSet"....

Kontroller om det kan være tilfældet, og brug eventuelt freeAndNil() til at frigøre "TCustomClientDataSet" (ikke interface), som vil kontrollere for om den ikke er NIL (not assigned) før den kalder .free

btw: Bruger altid freeAndNil i destructor, og kun ".free" inden i rutiner med lokale variabler...

//mbs
Avatar billede hrc Mester
24. april 2012 - 15:06 #2
Hej Morten.

Ejeren af fDSBase må vel være denne instans jeg debugger, ikke?

Jeg kan singlesteppe mig gennem proceduren og tjekker jeg self.name undervejs så får jeg det pågældende datasæt. FDBBase har en pointer-adresse så jeg må antage det er et eller andet sted inde i det interface, at noget peger på nil - men jeg ved ikke hvordan det skal debugges.
24. april 2012 - 15:27 #3
HEJ,

Bare en lille side kommentar:

For et lille 1 1/2 års tid siden havde jeg en opgave hvor en herboende læge / ven skulle analysere nogen patient/klientdata. Han var ikke nogen ørn til data og bad derfor mig gøre det programmeringsmæssige (tavshedspligt osv..).  Vi valgte i første omgang en ADO base men ændrede senere det til en anden base, da jeg på nettet fandt programmel som med lidt fiflen kunne åbne ADO-baser. Vi forudså et sikkerhedsproblem og valgte derfor en anden løsning i form af en anden databaseløsning. Det så ud til at fungere, lægen var tilfreds og jeg blev lidt rigere....

Jeg ved ikke om dette er relevant for din løsning, men da du indledningsvis skrev KLIENT kunne det være relevant.

KR
Avatar billede mbsnet Nybegynder
24. april 2012 - 15:30 #4
Ja, der hvor instansen af "TCustomClientDataSet" frigøres... så hele klassen er garanteret frigjort, og derfor fejl ved definering af dens parametre.

Bemærk i kode-blokken ovenover fejlen er beskyttet af "if Assigned(FDSBase) then" (køres ikke) og "ChangesMade" er en lokal variabel af rutinen...

Derfor prøv at beskytte frigørelsen (et niveau dybere) ved hjælp af freeAndNil();

eks.
cs:TCustomClientDataSet;
freeAndNil(cs);
//...
Avatar billede hrc Mester
24. maj 2012 - 06:43 #5
Hej Snestrup og Morten

Jeg tror nok jeg har løst det. I alt fald er frekvensen faldet rigtig meget da jeg i framens baseklasse-destructor gennemløber komponentene for TDataSet nedarvinger og lukker dem hvis det mangler.

Et typisk journalvindue har nok i omegnen af 20 af den slags instanser og hvis en er aktiv, så opretholdes forbindelsen til datamodulet ... der på en eller anden måde allerede er ved at blive frigivet.

Kan ikke påstå jeg har forstået fejlen, men de er næsten forsvundet og jeg sover bedre om natten.

Morten, læg et svar så får du en sjat for din deltagelse.

Snestrup, jeg kunne ikke rigtig bruge dit indlæg.

... resten tager jeg tilbage igen.
Avatar billede mbsnet Nybegynder
24. maj 2012 - 13:33 #6
helt ok,
24. maj 2012 - 15:13 #7
HEJ MSBNET,

Jeg havde egentlig heller ikke regnet med det. Det var ment som en lille side-bemærkning /-kommentar og egentlig ikke som et (reelt) input til dit problem. Så MSBNET skal have kreditten (og æren) for din løsning. HELT OK for mit vedkommende. NO PROBLEM(O)..

KR
24. maj 2012 - 15:17 #8
DAMN,

Jeg så forkert..

Byt MSBNET ud med HRC.  (sorry!) ..

KR
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester