0

I have a small procedure to retrieve some text from a database. This function is called several thousand times in a cycle.

procedure TMainForm.RetrieveKnowledgeText(const knowledge_id : Integer;
                                            var knowlegde_title : string;
                                            var knowledge_text : string;
                                            var knowledge_origin : string);
begin
   knowlegde_title:= '';
   knowledge_text:= '';
   knowledge_origin:= '';
   //get text + title
   UniQuery3.Params[0].Value:= knowledge_id;
   UniQuery3.Open;
   while not UniQuery3.Eof do
   begin
     if (UniQuery3phrase_class.Value = 7) then
       knowledge_text:= knowledge_text + #10#13
     else
     begin
      if (UniQuery3phrase_class.Value = 1) then
        knowlegde_title:= UniQuery3phrase_text.AsString;
      knowledge_text:= knowledge_text + UniQuery3phrase_text.AsString+' ';
     end;
     UniQuery3.Next;
   end;
   UniQuery3.Close;
   //get origin
   UniQuery4.Params[0].Value:= knowledge_id;
   UniQuery4.Open;
   if not UniQuery4.Eof then
      knowledge_origin:= AnsiLowercase(UniQuery4origin_filename.AsString);
   UniQuery4.Close;
end;

The above procedure is called inside this one:

procedure TMainForm.ContextualizeKnowledge(const knowledge_id : Integer;
                                           const knowledge_year : Integer;
                                           const knowledge_month : Integer;
                                           const knowledge_date : TDateTime;
                                           const total_comments : Integer;
                                           const title : string;
                                           const origin : string);
var
  knowledge_title : string;
  knowledge_text : string;
  knowledge_origin : string;
begin
  knowledge_title:= '';
  knowledge_text:= '';
  knowledge_origin:= '';
  RetrieveKnowledgeText(knowledge_id,
                        knowledge_title,
                        knowledge_text,
                        knowledge_origin);
  //save into a text file
  (...)
end;

The main cycle looks like this:

  UniQueryRetrieveLastKnowledge.Params[0].Value:= last_context_knowledge_id;
  UniQueryRetrieveLastKnowledge.Open;
  while not UniQueryRetrieveLastKnowledge.Eof do
  begin
    ContextualizeKnowledge(UniQueryRetrieveLastKnowledge.FieldByName('knowledge_id').AsInteger,
                           main_year,
                           main_month,
                           UniQueryRetrieveLastKnowledge.FieldByName('knowledge_date').AsDateTime,
                           UniQueryRetrieveLastKnowledge.FieldByName('total_comments').AsInteger,
                           UniQueryRetrieveLastKnowledge.FieldByName('knowledge_description').AsString,
                           UniQueryRetrieveLastKnowledge.FieldByName('public_filename_or_url').AsString);
    //
    UniQueryRetrieveLastKnowledge.Next;
  end;
  UniQueryRetrieveLastKnowledge.Close;

My application memory usage keeps increasing by 4k until it hangs. I know this is not a specific question, but I can't find the leak. Can anyone point out what I'm doing wrong?

Miguel E
  • 1,316
  • 2
  • 17
  • 39
  • 1
    Put FastMM full debug in your project and see if it can detect your leaks. What made you decide that the code in the Q contains the fault? – David Heffernan Apr 04 '14 at 21:26
  • I'm not experienced with FastMM. I've commented out everything else, so the only thing remaining, beside this code, is the Unidac framework (from Devart) and Delphi units. – Miguel E Apr 04 '14 at 21:28
  • Now is the time to get that experience – David Heffernan Apr 04 '14 at 21:29
  • Ok. Thank you, but at first glance do you see anything wrong with params passing between the procedures, or something else? – Miguel E Apr 04 '14 at 21:30
  • Nothing jumps out at me apart from the badly named query objects. – David Heffernan Apr 04 '14 at 21:30
  • This is a wild guess, but the mention of 4K jumped out at me and made me remember a question [I posted a long time ago](http://stackoverflow.com/questions/1071599/possible-to-force-delphi-threadvar-memory-to-be-freed). If you have a Delphi DLL that is being loaded/unloaded in this cycle, it *might* be a similar problem. – Mark Wilkins Apr 04 '14 at 21:35
  • There are no external DLL here, all VCL. Maybe the leak is inside the Unidac framework. I'm using v.4.1.4 and there are complaints about v.4.5.10 (http://forums.devart.com/viewtopic.php?f=28&t=25468) – Miguel E Apr 04 '14 at 21:40

1 Answers1

2

Nothing obvious leaps out of this code. Most likely if this code is responsible for leaks, then it will be the functions that this code calls that leak.

Debug this by adding FastMM full debug version to your project. It will find leaks, and give you call stacks that identify where the leaked memory was allocated. Invariably that is enough information to understand and fix the leaks.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490