Memory leak when internal pointer passed out as parameter

M

Mike

Hello,

I have following existing code. And there is memory leak. Anyone know
how to get ride of it? function foo has been used in thousands places,
the signature is not allowed to change.

Thanks in advance,



my_struc * foo1( )
{
my_struc * tmp;

tmp = (my_struc *)calloc(1, sizeof(my_struc));

return tmp;
}

void main()
{
my_struc *mainPtr;

mainPtr = foo1();

free(mainPtr);
}
 
B

Ben Pfaff

Mike said:
I have following existing code. And there is memory leak. Anyone know
how to get ride of it? function foo has been used in thousands places,
the signature is not allowed to change.

There's no memory leak visible in your code, although there's an
invalid declaration of main() and an unnecessary cast.
 
W

Walter Roberson

I have following existing code. And there is memory leak. Anyone know
how to get ride of it?

Are you certain that it is a memory leak, and not a memory
fragmentation problem?
 
M

Mike

Are you certain that it is a memory leak, and not a memory
fragmentation problem?

Rational Purify checked the code, and reported memory leak on foo1
when we allocate memory. I assum e that the compiler will allocate a
new block of memory when foo1 returns. Then the memory allocated
within foo1 will remain in the system heap forever. However I have no
way to verify it.
 
W

Walter Roberson

Mike said:
Rational Purify checked the code, and reported memory leak on foo1
when we allocate memory. I assum e that the compiler will allocate a
new block of memory when foo1 returns. Then the memory allocated
within foo1 will remain in the system heap forever. However I have no
way to verify it.

Your foo1 was:
my_struc * foo1( )
{
my_struc * tmp;

tmp = (my_struc *)calloc(1, sizeof(my_struc));

return tmp;
}


For that code, No, the compiler will NOT "allocate a new block of
memory when foo1 returns" with "the memory allocated within foo1"
reaming "in the system heap forever". Your foo1() will request
the allocation of memory, and it will directly return the pointer
to that memory, which is a simple return of a value. The memory
you allocated from within foo1() will remain allocated until you
free() it. If Purify is reporting that you have a memory leak
with respect to foo1() then there is some path in your program
that is not freeing the allocated memory.

Note that if you malloc() or calloc() a bunch of memory, and do
not free() it before you return from main() [e.g., because you know
that the OS is going to clean up everything for you], then as
far as Purify is concerned, you have a memory leak.
 
F

Flash Gordon

Mike wrote, On 03/04/07 19:52:
Please don't quote peoples signatures, generally the bit after "-- ",
unless you are commenting on them.
Rational Purify checked the code, and reported memory leak on foo1
when we allocate memory.

Find out how to get useful reports out of it then. This is not the
correct place to do that. Also ensure that it is the actual code posted
here that you checked, not something else.
> I assum e that the compiler will allocate a
new block of memory when foo1 returns.

What makes you think that?
> Then the memory allocated
within foo1 will remain in the system heap forever. However I have no
way to verify it.

Yes you, read a text book.

The code in question allocated some space with calloc, returned the
pointer obtained, and then freed it in the calling function. This is
completely correct and does not leak memory.
 
B

Ben Pfaff

Mike said:
Rational Purify checked the code, and reported memory leak on foo1
when we allocate memory. I assum e that the compiler will allocate a
new block of memory when foo1 returns. Then the memory allocated
within foo1 will remain in the system heap forever. However I have no
way to verify it.

The memory leak is undoubtedly the fault of foo1's caller: the
caller is the one that must free the memory region. Therefore,
check the set of functions up the call stack from foo1 to make
sure that they free the memory that foo1 allocates and returns.
 
K

Keith Thompson

Mike said:
Rational Purify checked the code, and reported memory leak on foo1
when we allocate memory. I assum e that the compiler will allocate a
new block of memory when foo1 returns. Then the memory allocated
within foo1 will remain in the system heap forever. However I have no
way to verify it.

(Please don't quote signatures.)

Her's the code you posted:

my_struc * foo1( )
{
my_struc * tmp;

tmp = (my_struc *)calloc(1, sizeof(my_struc));

return tmp;
}

void main()
{
my_struc *mainPtr;

mainPtr = foo1();

free(mainPtr);
}

There is no memory leak in that code, though there are other problems:

main returns int; change "void main()" to "int main(void)".

Add a "return 0;" at the end of your main function.

foo1 takes no arguments. You should say so explicitly:
"my_struc *foo1(void)".

Don't cast the result of malloc() or calloc().

It's very likely that malloc() is better than calloc(); calloc()
initializes the allocated memory to all-bits-zero, which is rarely
useful.

Read the FAQ, <http://www.c-faq.com>.

In general, there should be a call to free() for every call to
malloc() or calloc() (realloc() complicates things a bit, but you're
not using that). In the code you showed us, you properly free the
allocated memory. In the code you didn't show us, there must be a
case where you don't free the allocated memory. That's all we can
tell from what you've posted. Rational Purify found the memory leak
for you; can it be persuaded to tell you more about where it happens,
for example, where foo1 was called from?
 
E

Eric Sosman

Flash Gordon wrote On 04/03/07 15:20,:
Mike wrote, On 03/04/07 19:52:
[...]
Rational Purify checked the code, and reported memory leak on foo1
when we allocate memory.

Find out how to get useful reports out of it then. This is not the
correct place to do that. Also ensure that it is the actual code posted
here that you checked, not something else.

Since the posted code wouldn't even compile, I think
we can safely assume that no "ensuring" took place.
 
C

CBFalconer

Mike said:
I have following existing code. And there is memory leak. Anyone
know how to get ride of it? function foo has been used in thousands
places, the signature is not allowed to change.

my_struc * foo1( )
{
my_struc * tmp;

tmp = (my_struc *)calloc(1, sizeof(my_struc));
return tmp;
}

void main()
{
my_struc *mainPtr;

mainPtr = foo1();
free(mainPtr);
}

No leak exists. However that will not compile. There is no
declaration for my_struc, there is no #include <stdlib.h>, the
declaration of main is invalid. In addition the cast in the call
to calloc is unnecessary and foolish, and hides other errors.
 
M

Mr John FO Evans

Keith Thompson <[email protected]> said:
Don't cast the result of malloc() or calloc().

This intrigues me - please explain why.

Do you mean immediately as in the quoted code or do not cast any pointer
which has been generated by malloc/calloc?

John
 
F

Flash Gordon

Mr John FO Evans wrote, On 04/04/07 00:08:
This intrigues me - please explain why.

Search the group for the long discussions we have had on this. Also
check the comp.lang.c FAQ. Basically, if you do not cast the compiler is
REQUIRED to produce a diagnostic if you fail to include stdlib.h, a
mistake many newbies seem to make. Also why do extra typing that is not
required and clutters up the code?
Do you mean immediately as in the quoted code or do not cast any pointer
which has been generated by malloc/calloc?

He meant immediately as in the code that was posted. However, in general
you should not cast. There are a few situations where it is required,
but most of the time they will just stop the compiler from pointing out
your error without actually fixing it.
 
D

Daniel Rudy

At about the time of 4/3/2007 11:52 AM, Mike stated the following:
Rational Purify checked the code, and reported memory leak on foo1
when we allocate memory. I assum e that the compiler will allocate a
new block of memory when foo1 returns. Then the memory allocated
within foo1 will remain in the system heap forever. However I have no
way to verify it.

The allocated memory will be returned to the system heap when the
program exits, if there is a memory leak. I don't see a memory leak
either. The function foo1 calls calloc and returns the resulting
pointer, then the pointer is freed in you code.

A couple of points to make though:

1. Main is not declared correctly. It should be one of the two
following examples:

int main(void)

---or---

int main(int argc, char **argv)

In either case, you need to have a return at the end of your main function.

2. Your cast in calloc is not necessary...unless you are using C++, but
then you would need to head on over to c.l.c++ to ask your question.



--
Daniel Rudy

Email address has been base64 encoded to reduce spam
Decode email address using b64decode or uudecode -m

Why geeks like computers: look chat date touch grep make unzip
strip view finger mount fcsk more fcsk yes spray umount sleep
 
S

santosh

Daniel said:
At about the time of 4/3/2007 11:52 AM, Mike stated the following:


The allocated memory will be returned to the system heap when the
program exits, if there is a memory leak.

Nowhere does the C Standard guarantee this. Yes, modern memory
protected operating systems do reclaim a program's allocated memory
after the latter's termination, but C implementations exist on systems
that're not as sophisticated or capable. A conforming C program must
not make such assumptions.

You've also ignored the case of long-running processes like UNIX
deamons. Memory leaks in such programs can cause the system memory to
be slowly eaten up.

It's always better to explicitly free any memory when you're done with
it.

<snip>
 
D

Daniel Rudy

At about the time of 4/4/2007 4:20 AM, santosh stated the following:
Nowhere does the C Standard guarantee this. Yes, modern memory
protected operating systems do reclaim a program's allocated memory
after the latter's termination, but C implementations exist on systems
that're not as sophisticated or capable. A conforming C program must
not make such assumptions.

I don't know what the C standard says about alot of things, so thank you
for pointing that out. I do know that on some machines, if you don't
free the memory when the program exits, the host OS will die. Those are
few and far between in this day and age.
You've also ignored the case of long-running processes like UNIX
deamons. Memory leaks in such programs can cause the system memory to
be slowly eaten up.

Excellent point. I had forgotten about that. The thing with Unix is
that if the process keeps allocating memory until there is no more, then
either the process will die by itself, or the host OS will forcibly kill it.

I have written a complete set of wrapper functions for malloc(3) and
mmap(2) that solves the problem. The code is fully re-entrant since
everything is a pointer. So when a thread terminates, everything that
thread allocated also goes away. It keeps track of it using a open
chained hash table of pointers returned by malloc(3) and mmap(2).
It's always better to explicitly free any memory when you're done with
it.

I agree completely.

--
Daniel Rudy

Email address has been base64 encoded to reduce spam
Decode email address using b64decode or uudecode -m

Why geeks like computers: look chat date touch grep make unzip
strip view finger mount fcsk more fcsk yes spray umount sleep
 
W

websnarf

I have following existing code. And there is memory leak. Anyone know
how to get ride of it? function foo has been used in thousands places,
the signature is not allowed to change.

Thanks in advance,

my_struc * foo1( ) {
my_struc * tmp;
tmp = (my_struc *)calloc(1, sizeof(my_struc));
return tmp;
}

void main() {
my_struc *mainPtr;
mainPtr = foo1();
free(mainPtr);
}

You need to #include <stdlib.h>. Otherwise the compiler will easily
get confused about what calloc() is doing. The problem is that 1 will
be turned into an int, while sizeof(my_struct) will be turned into a
size_t. However, the declaration of calloc() requires two size_t's.
On most 32bit systems this doesn't matter, but on modern 64bit systems
this is a big deal size int and size_t are different sizes. This
would not be flagged as a "leak" however.
[...]

Rational Purify checked the code, and reported memory leak on foo1
when we allocate memory. I assume that the compiler will allocate a
new block of memory when foo1 returns. Then the memory allocated
within foo1 will remain in the system heap forever. However I have
no way to verify it.

Well the problem is that foo1() is an external function. So it can be
called outside of this file. *That* is likely where your real problem
is. I.e., you have some other file which is calling the function but
not calling free right after it. I'm a little surprised that R.P.
wouldn't tell you where the call sites for this problem are, but
presumably you can just grep for it.
 
C

Cameron Laird

[...]

Rational Purify checked the code, and reported memory leak on foo1
when we allocate memory. I assume that the compiler will allocate a
new block of memory when foo1 returns. Then the memory allocated
within foo1 will remain in the system heap forever. However I have
no way to verify it.

Well the problem is that foo1() is an external function. So it can be
called outside of this file. *That* is likely where your real problem
is. I.e., you have some other file which is calling the function but
not calling free right after it. I'm a little surprised that R.P.
wouldn't tell you where the call sites for this problem are, but
presumably you can just grep for it.
.
.
.
From everything I know, Purify *does* provide accurate
traceback information. I think it'd be quite valuable
for Mike to pursue this matter to a more complete anal-
ysis. While I presume his Purify license includes
support for such matters, maybe he'd feel more comfor-
table getting help from a third party ...

In any case, I suspect there's a non-magical explanation
for these symptoms. A good first step might be to clean
up the style of the source, as other follow-ups have
already commented.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top