Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2010-01

compile time memory leak detection

15 messages · 6 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

ik

Hello list,

There are sometimes way to "see" that you have memory leak in a code without using any sort of profiler.
For example using new/getmem on a local variable without releasing it etc...

Does FPC know how to find this places on compile time and at least issue a warning about it ?

Thanks,
Ido

http://ik.homelinux.org/

Reply by email

Marco van de Voort
to ik

In our previous episode, ik said:

Show quoted text 6 lines
There are sometimes way to "see" that you have memory leak in a code without using any sort of profiler. For example using new/getmem on a local variable without releasing it etc... Does FPC know how to find this places on compile time and at least issue a warning about it ?

Is this a suitable task for a compiler? Maybe it is a task better suited to an external profiler.

Reply by email

ik
to Marco van de Voort

http://ik.homelinux.org/

Marco van de Voort wrote 14 lines
In our previous episode, ik said: > There are sometimes way to "see" that you have memory leak in a code without > using any sort of profiler. > For example using new/getmem on a local variable without releasing it etc... > > Does FPC know how to find this places on compile time and at least issue a > warning about it ? Is this a suitable task for a compiler? Maybe it is a task better suited to an external profiler.

Well I find myself forgetting from time to time to close allocated memory on a local variable, and a nice warning can make it easier to figure out then running code and finding it after x amount of execution time (and using the feature that uses that code).

So, I do not know if it's really a compiler task, but it sure can help :)

_______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Ido

Reply by email

Jonas Maebe
to ik: There are sometimes way to "see" that you have memory leak in a code without using any…
ik wrote 9 lines
There are sometimes way to "see" that you have memory leak in a code without using any sort of profiler. For example using new/getmem on a local variable without releasing it etc... Does FPC know how to find this places on compile time and at least issue a warning about it ?

No, it doesn't. In principle, the compiler can't even be sure that you haven't replaced the default memory manager with e.g. some garbage- collector-style memory manager similar to Boehm GC, in which case such warnings would be wrong.

Jonas

Reply by email

Nikolai Zhubr
to Jonas Maebe

19.01.2010 12:31, Jonas Maebe:

Show quoted text 8 lines
> Does FPC know how to find this places on compile time and at least > issue a > warning about it ? No, it doesn't. In principle, the compiler can't even be sure that you haven't replaced the default memory manager with e.g. some garbage-collector-style memory manager similar to Boehm GC, in which case such warnings would be wrong.

May I put it a bit other way?
Would it be possible/feasable to introduce some (optional) restrictions and/or extensions to pointer-related syntax and/or pointer-related parts of RTL so as to completely ensure safety if pointer operations?

This would probably include:
- guaranree that dynamically allocated will not be silently lost (leak)
- guaranree that dynamically allocated mem will not be disposed twice;
- guarantee that dynamically allocated mem will not be accessed beyond the respective allocation size.

I'd guess this would require huge work and substantial modifications to the language though. And probably, this is not possible without GC, and I don't like GCs anyway :)

Nikolai

Show quoted text 8 lines
Jonas _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Thaddy
to Nikolai Zhubr
Nikolai Zhubr wrote
I'd guess this would require huge work and substantial modifications to the language though.

The compiler then has to assert all possible codepaths... Do you think that's a viable option?

Reply by email

Nikolai Zhubr
to Thaddy

19.01.2010 16:16, Thaddy:

Show quoted text 5 lines
Nikolai Zhubr wrote: > I'd guess this would require huge work and substantial modifications > to the language though. The compiler then has to assert all possible codepaths... Do you think that's a viable option?

I don't have that much expertise to judge really, but I'd suppose this can't be done at compile time completely.
On the other hand, refcounting at run-time could work, theoretically. (IIRC long strings use refcounting already)

Nikolai

Reply by email

JoshyFun
to Nikolai Zhubr: 19.01.2010 12:31, Jonas Maebe: May I put it a bit other way? Would it be…

Hello Nikolai,

Tuesday, January 19, 2010, 1:38:53 PM, you wrote:

NZ> This would probably include:
NZ> - guaranree that dynamically allocated will not be silently lost (leak) NZ> - guaranree that dynamically allocated mem will not be disposed twice; NZ> - guarantee that dynamically allocated mem will not be accessed beyond NZ> the respective allocation size.

That's impossible to the compiler, it is a runtime task (heaptrc):

procedure weird();
var
  p: pchar;
begin
  GetMem(p,10);
  inc(p,random(30));
  p^:='A';
end;
Best regards, JoshyFun

Reply by email

Nikolai Zhubr
to JoshyFun

19.01.2010 17:49, JoshyFun пишет:

Show quoted text 5 lines
var p: pchar; begin GetMem(p,10); inc(p,random(30));

Yes, this is among things which should probably be immediately disallowed at compile-time (as long as one wants reasonably safe pointers) because they are hard (or expensive) to validate later.

I usually try to not use raw pointer arithmetics and either use new/dispose with typed pointers or constructs like GetMem(X, SizeOf(X^)). However, compiler does not force me to do so.

Nikolai

Reply by email

Marco van de Voort
to Nikolai Zhubr

In our previous episode, Nikolai Zhubr said:

Show quoted text 8 lines
> p: pchar; > begin > GetMem(p,10); > inc(p,random(30)); Yes, this is among things which should probably be immediately disallowed at compile-time (as long as one wants reasonably safe pointers) because they are hard (or expensive) to validate later.

To the compiler random is just another procedure. It doesn't grasp that it gives back random values.

FPC is not going to forbid standard pointer use, since it breaks a lot of code.

I usually try to not use raw pointer arithmetics and either use new/dispose with typed pointers or constructs like GetMem(X, SizeOf(X^)). However, compiler does not force me to do so.

In theory, of course a dialect, or dialect switch could be implemented. It could be even combined with an ISO Pascal mode. But the question is always who is going to do it, and who is going to support it long term?

Reply by email

Nikolai Zhubr
to Marco van de Voort

19.01.2010 23:18, Marco van de Voort:

FPC is not going to forbid standard pointer use, since it breaks a lot of code.

Of course. I think it all was about new features for new code. By the way, it reminds me MemAvail (though not exactly the same). Lots of code used to use it, however AFAIK it is not available anymore (for a clear reason that it is inappropriate for any modern code)

Show quoted text 7 lines
> I usually try to not use raw pointer arithmetics and either use > new/dispose with typed pointers or constructs like GetMem(X, > SizeOf(X^)). However, compiler does not force me to do so. In theory, of course a dialect, or dialect switch could be implemented. It could be even combined with an ISO Pascal mode. But the question is always who is going to do it, and who is going to support it long term?

This is understood. I was just speculating theoretically.

Nikolai

Reply by email

Marco van de Voort
to Nikolai Zhubr

In our previous episode, Nikolai Zhubr said:

Show quoted text 7 lines
19.01.2010 23:18, Marco van de Voort: > FPC is not going to forbid standard pointer use, since it breaks a lot of > code. Of course. I think it all was about new features for new code. By the way, it reminds me MemAvail (though not exactly the same). Lots of code used to use it, however AFAIK it is not available anymore (for a clear reason that it is inappropriate for any modern code)

Totally different issue. The problem is that there was no implementation of memavail that would suit the usage of memavail in old dos code.

That was the simple difference between single- and multiprocessing, which was ingrained in the use. Even the simple showing available memory like Turbo Vision apps sometimes did would lead to strange behaviour (one minute it would look like memory was running low, and then later when an additional block was allocated from memory, there would be plenty free memory again)

It would become even more confusing when you tried to make decisions based on it. (like trying to allocate a big as possible block to be used as cache). When one would let memavail return the memory available in the heap currently allocated it was too little. If you'd let it return the memory globally available, your risk starving other apps for memory (*), and allocating huge chunks to former 64k apps that won't use more than a few 100ks.

There was really no solution then.

(*) not to speak of the fact that a lot of systems returned virtual memory
as free memory.

Reply by email

JoshyFun
to Nikolai Zhubr: 19.01.2010 17:49, JoshyFun пишет: Yes, this is among things which should probably be…

Hello Nikolai,

Tuesday, January 19, 2010, 8:10:49 PM, you wrote:

NZ> 19.01.2010 17:49, JoshyFun ?????:

Show quoted text 5 lines
> var > p: pchar; > begin > GetMem(p,10); > inc(p,random(30));

NZ> Yes, this is among things which should probably be immediately NZ> disallowed at compile-time (as long as one wants reasonably safe NZ> pointers) because they are hard (or expensive) to validate later.

NZ> I usually try to not use raw pointer arithmetics and either use NZ> new/dispose with typed pointers or constructs like GetMem(X, NZ> SizeOf(X^)). However, compiler does not force me to do so.

Pointers and safe code is mutually exclusive, like managed code and fast execution, garbage collection and memory optimization, ...

In example this will work in some machines and crash in others:

GetMem(p,1024*1024*1024);
p^:=#0;

You can not detect it a compile time in any way.

Best regards, JoshyFun

Reply by email

Nikolai Zhubr
to Marco van de Voort: In our previous episode, Nikolai Zhubr said: Totally different issue. The problem is that…

20.01.2010 0:22, Marco van de Voort:

Show quoted text 18 lines
Totally different issue. The problem is that there was no implementation of memavail that would suit the usage of memavail in old dos code. That was the simple difference between single- and multiprocessing, which was ingrained in the use. Even the simple showing available memory like Turbo Vision apps sometimes did would lead to strange behaviour (one minute it would look like memory was running low, and then later when an additional block was allocated from memory, there would be plenty free memory again) It would become even more confusing when you tried to make decisions based on it. (like trying to allocate a big as possible block to be used as cache). When one would let memavail return the memory available in the heap currently allocated it was too little. If you'd let it return the memory globally available, your risk starving other apps for memory (*), and allocating huge chunks to former 64k apps that won't use more than a few 100ks. There was really no solution then.

Well, you are right of course. I just meant that a sole existance of some code relying on some feature does not necessarily prove this feature is sane enough for all times.
Standard pointer arithmetics is not inherently broken as memavail. It is even usefull. However, a small mistake in such code also leads to strange behaviour, and we humans tend to sometimes make mistakes...

Show quoted text 8 lines
(*) not to speak of the fact that a lot of systems returned virtual memory as free memory. _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Nikolai Zhubr
to JoshyFun: NZ> 19.01.2010 17:49, JoshyFun ?????: NZ> Yes, this is among things which should probably…

20.01.2010 0:29, JoshyFun:

Pointers and safe code is mutually exclusive, like managed code and

I use pointers quite a lot. The code then works 24/7 for months under some continuous load. (Still, I'd be even happier if compiler/RTL double-checked my code additionally.)

fast execution, garbage collection and memory optimization, ...

I'm no expert in GCs, but it seems too general.

Show quoted text 7 lines
In example this will work in some machines and crash in others: GetMem(p,1024*1024*1024); p^:=#0; You can not detect it a compile time in any way.

Sure, however this code is actually safe. (if allocation was successfull, then execution goes on normally, otherwise an exception will be raised on all reasonable platforms I suppose)

Reply by email