I've tested my application using one debugger, and the results are that
there are some memory leaks, most of them involving the use of strings, like
in this case:
var
s: String;
begin
s:=ProcThatFillsTheStr(bla,bla);
DoSomethingWithString(s);
end;
The debugger says that 's' generates a memory leak, but shouldn't it be
freed automatically by the delphi compiler?
What should I do? Pass the 's' string as a var parameter to the function?
Call finalitze or SetLength(s,0) at the end of the procedure?
Thnaks!
Thanks for the fast answer!
1.- The debugger is AQTime 3.1
2.- ProcThatFillsTheStr fills it like this:
result:=s1+s2;
Where s1 and s2 are strings, too.
3.- DoSomethingWithString(s) only assigns s to another string, like this:
obj.str:=s;
Arnau, Some questions:
>Thanks for the fast answer!
>1.- The debugger is AQTime 3.1
>2.- ProcThatFillsTheStr fills it like this:
> result:=s1+s2;
> Where s1 and s2 are strings, too.
>3.- DoSomethingWithString(s) only assigns s to another string, like this:
> obj.str:=s;
Based on that, I'd say there's a bug in your debugger<g>. It may
think that the original value of S is not deallocated (which is true)
because the function result is plugged directly into S. But since the
original value of S is an empty string, there is no need to deallocate
it before the assignment, and Delphi generates no code to do so.
Good luck.
Kurt
One easy way to find out is to put the code in a big loop. Run it 10,000
times
and see if the apps memory usage is going up.
Under Delphi 4, we ran into issues with string returning functions and
memory
leakage. It was extremely strange. The app would just forget about the
memory
in the result. When we changed the function call to a proc( var string), the
memory
leak started appearing as soon as we used the string. We tried it under
Delphi 7
and the entire thing went away, so we didn't bother trying to figure it out.
Thanks,
Brett
"Kurt Barthelmess (TeamB)" <kbarth...@compuserve.com> wrote in message
news:3fc35720....@newsgroups.borland.com...
Regards,
Gabriel
"Kurt Barthelmess (TeamB)" <kbarth...@compuserve.com> wrote in message
news:3fc35720....@newsgroups.borland.com...
>I'd rather think that obj is not properly destroyed.
>Because strings are reference counted, when s is deallocated the actual
>string remains assigned to obj.str. If this is not deallocated, the result
>is that the string allocated in s was not freed.
imho, that is a bug in the debugger. If it tells you that something (S
in this case) was not deallocated when it clearly is, then it is not
only unhelpful, but misleading in its warnings. Had it said that
"obj.str" was not deallocated, you'd have something useful to go on.
Kurt
var
s : string;
P : Pointer;
PP: PRec;
begin
s := 'hello';
new(PP);
PP.str := s;
P := PP;
//only one of these
dispose(P);//this will produce the leak
dispose(PP);//this is ok
end;
Gabriel
"Kurt Barthelmess (TeamB)" <kbarth...@compuserve.com> wrote in message
news:3fc3ddb0...@newsgroups.borland.com...
>This is not quite right. It doesn't say "who" (as a variable) is not
>deallocated; it sais that "something" (memory area) is not deallocated and
>it shows you where it was allocated (s in this case). There is no way to
>tell you where it should be deallocated. S was deallocated, but the memory
>reference counter was only decremented because it is still used somewhere
>else.
I understand what it is doing. But it would not be helpful to me to
get such an advisory that is so misleading.
>I recently found a lot of this
>kind of leaks.
[clip]
> dispose(P);//this will produce the leak
I don't know how to answer that except to ask "What did you expect?"
Kurt
> "Arnau Font" <af...@nospam-ipssoft.com> wrote:
>
> > Thanks for the fast answer!
> > 1.- The debugger is AQTime 3.1
> > 2.- ProcThatFillsTheStr fills it like this:
> > result:=s1+s2;
> > Where s1 and s2 are strings, too.
> > 3.- DoSomethingWithString(s) only assigns s to another string, like
> > this: obj.str:=s;
>
> Based on that, I'd say there's a bug in your debugger<g>.
Perhaps S is a global variable? In that case it may never be explicitly
cleared, although Windows will take care of that after the program has
ended.
--
Rudy Velthuis (TeamB)
"The only thing necessary for the triumph of evil is for good men to do
nothing."
-- Edmund Burke (1729-1797)
> I understand what it is doing. But it would not be helpful to me to
> get such an advisory that is so misleading.
Yes, I agree it is a little misleading, but that's when you don't consider
reference counting; once you understand it's easier to look at the right
direction. I keep repeating: do you see a way to tell where should be the
string destroyed?
This problem is the same when working with classic memory allocations; you
reserve a space, store the pointer than later deallocate when you don't need
it anymore. The profiler can help and show you where you allocated the
space; it's your problem to know where to deallocate it.
> >I recently found a lot of this
> >kind of leaks.
> [clip]
> > dispose(P);//this will produce the leak
>
> I don't know how to answer that except to ask "What did you expect?"
This simple example is what I think it happens in his situation. As I said,
I believe he should see where the string is going; it is very likely to
happen this way exactly because in general the strings are properly
deallocated.
On the other hand maybe the example was not clear enough; you can have a
large number of fields in the record (any kind except strings and
interfaces) and they will be properly destroyed with dispose(P), only the
string not. If you look at the CPU listing you see that exactly the finalize
call is missing.
What I wanted to point is that probably he is deallocating the pointer but
via a generic pointer and that could be the cause. I believe this because
otherwise he would get other leak reports about the record.
Gabriel
>Perhaps S is a global variable? In that case it may never be explicitly
>cleared, although Windows will take care of that after the program has
>ended.
Except that Arnau wrote:
>Call finalitze or SetLength(s,0) at the end of the procedure?
Kurt
>Yes, I agree it is a little misleading, but that's when you don't consider
>reference counting; once you understand it's easier to look at the right
>direction. I keep repeating: do you see a way to tell where should be the
>string destroyed?
That isn't possible to do, of course. And I don't have a problem with
the debugger telling me that such and such a memory block has a
non-zero reference count. It might even tell me, "Here is a list of
the places the count was bumped, and here's a list of the places it
was decremented." But telling me the problem is "here" when it is
actually "there" is a problem. A magician does this professionally,
but the debugger is not on stage<g>.
>On the other hand maybe the example was not clear enough; you can have a
>large number of fields in the record (any kind except strings and
>interfaces) and they will be properly destroyed with dispose(P), only the
>string not. If you look at the CPU listing you see that exactly the finalize
>call is missing.
Yes. Which is why I wrote "What did you expect?" Using an untyped
pointer is a terrible practice, imho. One of the strong points of OP
over C (as far as Delphi users are concerned, of course, C programmers
would not agree<g>) is its strong typing. To deliberately obfuscate
code like that can't be considered good practice.
Kurt
That might be one case, and I'm looking at it, but I have other memory leaks
like this one:
procedure TFInicial.TimerMemoriaTimer(Sender: TObject);
var
Memo:THeapStatus;
begin
TimerMemoria.Enabled:=false;
Memo:=GetHeapStatus;
laMem.Caption:=IntToStr(Memo.TotalAllocated); //Here sometimes there is a
memory leak
EstadistiquesManager.Obertures(num, perce); //Global variable
//In the format function sometimes causes another memory leak
laObertures.Caption:=Format('%d (%2f%%)',[num, perce]);
TimerMemoria.Enabled:=true;
end;
Any ideas? I just can't get the point.As you see, there are no pointers
involved.
The problem is that my application should be active 'for ages' so memory
leaks are quite a problem.
Thanks!
Arnau.
>I have other memory leaks
>like this one:
>
>procedure TFInicial.TimerMemoriaTimer(Sender: TObject);
>var
> Memo:THeapStatus;
>begin
> TimerMemoria.Enabled:=false;
> Memo:=GetHeapStatus;
> laMem.Caption:=IntToStr(Memo.TotalAllocated); //Here sometimes there is a
>memory leak
What is "laMem"? If it is a TLabel or similar standard component,
there is no memory leak there.
> EstadistiquesManager.Obertures(num, perce); //Global variable
> //In the format function sometimes causes another memory leak
> laObertures.Caption:=Format('%d (%2f%%)',[num, perce]);
I can't tell what is going on here with the external call, but the
Format function is one that, like assigning a Caption to a TLabel,
does not leak memory.
>Any ideas? I just can't get the point.As you see, there are no pointers
>involved.
No untyped pointers at least. Technically the strings and the
parameters to Format are. But those are being cleaned up.
>The problem is that my application should be active 'for ages' so memory
>leaks are quite a problem.
Your application may have memory leaks, but I don't think this is
where they are occuring. Have you tried any of the other memory
debuggers? I sincerely think AQTime may be missing some deallocations
and giving you misleading warnings.
Good luck.
Kurt
Yes, it is a TLabel, sorry, that's why I find it so strange.
>
> Your application may have memory leaks, but I don't think this is
> where they are occuring. Have you tried any of the other memory
> debuggers? I sincerely think AQTime may be missing some deallocations
> and giving you misleading warnings.
Yeah, probably you are right, because this is wierd.
Could you recommend me any other memory debugger? I'll give them a try.
Thanks!
Only one memory leak remaining ;)
Thanks!
Sorry about all the mess! Thanks a lot for your comments!
"Arnau Font" <af...@nospam-ipssoft.com> wrote in message
news:3fc34bf4$1...@newsgroups.borland.com...
> "Rudy Velthuis (TeamB)" <rvel...@gmx.de> wrote:
>
> > Perhaps S is a global variable?
> Except that Arnau wrote:
>
> > Call finalitze or SetLength(s,0) at the end of the procedure?
Oh, I missed that.
--
Rudy Velthuis (TeamB)
"In theory, there is no difference between theory and practice. But, in
practice, there is."
- Jan L.A. van de Snepscheut
>Could you recommend me any other memory debugger? I'll give them a try.
Sorry, but I don't recommend stuff I haven't used. And I've been very
lucky in that I've never run into this sort of memory leak before so I
have not needed such a debugger. Someone else may have some
suggestions.
Good luck.
Kurt