memleak reported in valgrind

J

John Green

Hi,

I was learning how to use valgrind and was trying various projects and
checking the results. I used the following source code and I was
surprised by results. When I run the program with 1 argument I get a
memory leak. If I run the program with 2 or more arguments I valgrind
reports no memory leak.

So is there a memory leak??


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv) {
size_t numofelements;
size_t temp;
char **stringarray;

numofelements=argc-1;

if (numofelements == 1) {
numofelements=strlen(argv[1]);
stringarray=malloc(numofelements * sizeof(*stringarray));
if (stringarray == NULL) {
printf("can't allocate memory\n");
exit(EXIT_FAILURE);
}
for (temp=0; temp < numofelements; temp++) {
stringarray[temp]= malloc(2 * sizeof(char)); /* space for letter
+ \0 char */
if (stringarray[temp] == NULL) {
printf("can't allocate memory\n");
exit(EXIT_FAILURE);
}
strncpy(&stringarray[temp][0], &argv[1][temp], 1);
strncpy(&stringarray[temp][1], "\0", 1);
}
}
else {
stringarray=malloc(numofelements * sizeof(*stringarray));
if (stringarray == NULL) {
printf("can't allocate memory\n");
exit(EXIT_FAILURE);
}
for (temp=0; temp < numofelements; temp++) {
stringarray[temp] = argv[temp+1];
}
}

for (temp=0; temp < numofelements; temp++) {
printf("%s\n", stringarray[temp]);
}

free(stringarray);
return 0;
}
 
I

Ian Collins

Hi,

I was learning how to use valgrind and was trying various projects and
checking the results. I used the following source code and I was
surprised by results. When I run the program with 1 argument I get a
memory leak. If I run the program with 2 or more arguments I valgrind
reports no memory leak.

Why the surprise? One argument follows a differeent path.
So is there a memory leak??
Yes.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main(int argc, char **argv) {
size_t numofelements;
size_t temp;
char **stringarray;

numofelements=argc-1;

if (numofelements == 1) {
numofelements=strlen(argv[1]);
stringarray=malloc(numofelements * sizeof(*stringarray));
if (stringarray == NULL) {
printf("can't allocate memory\n");
exit(EXIT_FAILURE);
}
for (temp=0; temp< numofelements; temp++) {
stringarray[temp]= malloc(2 * sizeof(char)); /* space for letter
+ \0 char */

* here!
if (stringarray[temp] == NULL) {
printf("can't allocate memory\n");
exit(EXIT_FAILURE);
}
strncpy(&stringarray[temp][0],&argv[1][temp], 1);
strncpy(&stringarray[temp][1], "\0", 1);
}
}
else {
stringarray=malloc(numofelements * sizeof(*stringarray));
if (stringarray == NULL) {
printf("can't allocate memory\n");
exit(EXIT_FAILURE);
}
for (temp=0; temp< numofelements; temp++) {
stringarray[temp] = argv[temp+1];
}
}

for (temp=0; temp< numofelements; temp++) {
printf("%s\n", stringarray[temp]);
}

free(stringarray);
return 0;
}
 
J

John Green

I was learning how to use valgrind and was trying various projects and
checking the results.  I used the following source code and I was
surprised by results.  When I run the program with 1 argument I get a
memory leak.  If I run the program with 2 or more arguments I valgrind
reports no memory leak.

Why the surprise?  One argument follows a differeent path.
So is there a memory leak??
Yes.

     for (temp=0; temp<  numofelements; temp++) {
       stringarray[temp]= malloc(2 * sizeof(char)); /* space for letter
+ \0 char */

* here!

Thank you for pointing this out but I don't see it. I malloc an array
of strlen(argc-1). I then malloc 2 characters to store the character
and the \0 character to terminate the array.

What did I do wrong?
 
I

Ian Collins

I was learning how to use valgrind and was trying various projects and
checking the results. I used the following source code and I was
surprised by results. When I run the program with 1 argument I get a
memory leak. If I run the program with 2 or more arguments I valgrind
reports no memory leak.

Why the surprise? One argument follows a differeent path.
So is there a memory leak??
Yes.

for (temp=0; temp< numofelements; temp++) {
stringarray[temp]= malloc(2 * sizeof(char)); /* space for letter
+ \0 char */

* here!

Thank you for pointing this out but I don't see it. I malloc an array
of strlen(argc-1). I then malloc 2 characters to store the character
and the \0 character to terminate the array.

What did I do wrong?

Not freeing the blocks of two characters.
 
J

J. J. Farrell

John said:
Hi,
I was learning how to use valgrind and was trying various projects and
checking the results. I used the following source code and I was
surprised by results. When I run the program with 1 argument I get a
memory leak. If I run the program with 2 or more arguments I valgrind
reports no memory leak.
Why the surprise? One argument follows a differeent path.
So is there a memory leak?? Yes.

for (temp=0; temp< numofelements; temp++) {
stringarray[temp]= malloc(2 * sizeof(char)); /* space for letter
+ \0 char */
* here!

Thank you for pointing this out but I don't see it. I malloc an array
of strlen(argc-1). I then malloc 2 characters to store the character
and the \0 character to terminate the array.

What did I do wrong?

How many malloc()s did you do? How many free()s did you do?
 
I

Ivan Sichmann Freitas

You must free each two char block on string array. A easy way to see
where the memory leaks happen is by compiling your program with -g (if
you're using gcc, -ggdb3 is better), and valgrind will report the
lines in your code where the leak appear.
 
M

Mark Bluemel

Hi,

I was learning how to use valgrind and was trying various projects and
checking the results.  I used the following source code and I was
surprised by results.  When I run the program with 1 argument I get a
memory leak.  If I run the program with 2 or more arguments I valgrind
reports no memory leak.

So is there a memory leak??

Of course there is. Why don't you simplify your code to the 1 argument
case, and you should see exactly where the leak is.

See below, where I've snipped your code down to the leaking case.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv) {
size_t numofelements;
size_t temp;
char **stringarray;
    numofelements=strlen(argv[1]);
    stringarray=malloc(numofelements * sizeof(*stringarray));

1 malloc
    for (temp=0; temp < numofelements; temp++) {
      stringarray[temp]= malloc(2 * sizeof(char));

"n" mallocs
  free(stringarray);

1 free, leaving "n" mallocs unaccounted for.
  return 0;

}

Your code is pretty horrid in other ways, too. Using strncpy() to
handle single characters seems perverse.
 
J

John Green

On 09/20/10 12:14 PM, John wrote:
Hi,
I was learning how to use valgrind and was trying various projects and
checking the results.  I used the following source code and I was
surprised by results.  When I run the program with 1 argument I get a
memory leak.  If I run the program with 2 or more arguments I valgrind
reports no memory leak.
Why the surprise?  One argument follows a differeent path.
So is there a memory leak??
Yes.
      for (temp=0; temp<    numofelements; temp++) {
        stringarray[temp]= malloc(2 * sizeof(char)); /* space for letter
+ \0 char */
* here!
Thank you for pointing this out but I don't see it.  I malloc an array
of strlen(argc-1).  I then malloc 2 characters to store the character
and the \0 character to terminate the array.
What did I do wrong?

Not freeing the blocks of two characters.

I added the following to the end of the program but valgrind still
says I am leaking memory.

for(temp = numofelements; temp == 0; temp--){
free(stringarray[temp]);
}

Did I miss something?
 
I

Ian Collins

On Sep 19, 7:23 pm, Ian Collins wrote:
On 09/20/10 12:14 PM, John wrote:

I was learning how to use valgrind and was trying various projects and
checking the results. I used the following source code and I was
surprised by results. When I run the program with 1 argument I get a
memory leak. If I run the program with 2 or more arguments I valgrind
reports no memory leak.
Why the surprise? One argument follows a differeent path.
So is there a memory leak??

for (temp=0; temp< numofelements; temp++) {
stringarray[temp]= malloc(2 * sizeof(char)); /* space for letter
+ \0 char */
Thank you for pointing this out but I don't see it. I malloc an array
of strlen(argc-1). I then malloc 2 characters to store the character
and the \0 character to terminate the array.
What did I do wrong?

Not freeing the blocks of two characters.

I added the following to the end of the program but valgrind still
says I am leaking memory.

for(temp = numofelements; temp == 0; temp--){
free(stringarray[temp]);
}

Did I miss something?

At lest two things. The loop never runs (check the condition) and even
if it did, it would free something you haven't allocated and miss
something you have.
 
S

Seebs

I added the following to the end of the program but valgrind still
says I am leaking memory.
for(temp = numofelements; temp == 0; temp--){
free(stringarray[temp]);
}
Did I miss something?

Yes. This loop can't possibly do anything.

You start by setting temp to numofelements. Then, as long as temp is
zero, you....

oh, wait. temp wasn't zero. The loop body doesn't execute even once.

Try:

for (temp = 0; temp < numofelements; ++temp) {
free(stringarray[temp]);
}

.... and just to save you the next question, be sure you do this
*BEFORE* you free stringarray itself.

-s
 
G

Geoff

On Sep 19, 7:23 pm, Ian Collins wrote:
On 09/20/10 12:14 PM, John wrote:

I was learning how to use valgrind and was trying various projects and
checking the results.  I used the following source code and I was
surprised by results.  When I run the program with 1 argument I get a
memory leak.  If I run the program with 2 or more arguments I valgrind
reports no memory leak.
Why the surprise?  One argument follows a differeent path.
So is there a memory leak??

      for (temp=0; temp<    numofelements; temp++) {
        stringarray[temp]= malloc(2 * sizeof(char)); /* space for letter
+ \0 char */
Thank you for pointing this out but I don't see it.  I malloc an array
of strlen(argc-1).  I then malloc 2 characters to store the character
and the \0 character to terminate the array.
What did I do wrong?

Not freeing the blocks of two characters.

I added the following to the end of the program but valgrind still
says I am leaking memory.

for(temp = numofelements; temp == 0; temp--){
free(stringarray[temp]);
}

Did I miss something?

You can do it two ways, you can free them once you print them (since
you are about to discard them anyway) or you can free them just before
you free stringarray.

for (temp=0; temp < numofelements; temp++) {
printf("%s\n", stringarray[temp]);
free(stringarray[temp]);
}

free(stringarray);

return 0;
}

-OR-

for (temp=0; temp < numofelements; temp++) {
printf("%s\n", stringarray[temp]);
}

for (temp=0; temp < numofelements; temp++) {
free(stringarray[temp]);
}

free(stringarray);

return 0;
}
 
K

Kenny McCormack

Richard said:
Yes. Running it even ONCE through a debugger which would show you you
don't know how to write a for loop.

Had you done that you could have solved the issue like *that* (!)
yourself since a very obvious error would have been instantly revealed.

Yes, but as you well know, real men (men of CLC!) don't use debuggers.

And it is every little posters dream to be a big man, like the men of
CLC.

--
(This discussion group is about C, ...)

Wrong. It is only OCCASIONALLY a discussion group
about C; mostly, like most "discussion" groups, it is
off-topic Rorsharch [sic] revelations of the childhood
traumas of the participants...
 
T

Tom St Denis

Most of the regs are morons when it comes to understanding how much more
productive a debugger can make them.

Which might be very well true if it were actually the position of C
developers that "real men don't use debuggers."

Again, stop trolling CLC, go outside while the weather is still nice.
Seriously. Get a life.

Tom
 
K

Kenny McCormack

Tom St Denis said:
Which might be very well true if it were actually the position of C
developers that "real men don't use debuggers."

Who said anything about "C developers"? Please learn to read (while you
still can).

--
"The anti-regulation business ethos is based on the charmingly naive notion
that people will not do unspeakable things for money." - Dana Carpender

Quoted by Paul Ciszek (pciszek at panix dot com). But what I want to know
is why is this diet/low-carb food author doing making pithy political/economic
statements?

Nevertheless, the above quote is dead-on, because, the thing is - business
in one breath tells us they don't need to be regulated (which is to say:
that they can morally self-regulate), then in the next breath tells us that
corporations are amoral entities which have no obligations to anyone except
their officers and shareholders, then in the next breath they tell us they
don't need to be regulated (that they can morally self-regulate) ...
 
T

Tom St Denis

Who said anything about "C developers"?  Please learn to read (while you
still can).

I like to assume that the "regs" which you like to rag on are probably
developers.

But even if a CLC reg [other than yourself and the other trolls] did
in fact say that they don't use debuggers what the **** does that have
to do with anything? The reply [about using valgrind/debugger] was
that of a developmental nature not language specifics, so your rant is
ill suitable for the conversation.

Seriously man, you have but one life to live and whereas you could be
outside enjoying life you're cooped up at the computer trolling a
highly obscure, and technical USENET group. Are you really this
pathetically lifeless that you have to do this for kicks to stir up
your otherwise humdrum and useless existence?
 
S

Seebs

Which might be very well true if it were actually the position of C
developers that "real men don't use debuggers."

I have never met a C programmer who didn't ever use a debugger. Now,
there's plenty of room for variance. I have a coworker who will use
a debugger in places where I'd use logging, and I know people who would
use logging when I'd use a debugger, but...

A debugger is a pretty awesome tool. It's usually my first step in
pretty much any task.

-s
 
B

BGB / cr88192

Seebs said:
I have never met a C programmer who didn't ever use a debugger. Now,
there's plenty of room for variance. I have a coworker who will use
a debugger in places where I'd use logging, and I know people who would
use logging when I'd use a debugger, but...

A debugger is a pretty awesome tool. It's usually my first step in
pretty much any task.

I usually use a debugger if something is crashing somewhere or going
horridly wrong (or if I really can't figure out the problem from the source
or the logs).

I usually use logs for everything which looks out of place or may be useful
to note (just I prefer to keep common events out of the logs, as it is kind
of a hassle trying to find the cause of a bug when sifting through 10,000
open and close file messages).

sometimes, it would be nice to know the backtraces for logged events, but
these are awkward to gain and would waste a lot of space in the logs...

maybe a hybrid of a typical debugger and a log tool would be nice, where log
events are noted and captured by the debugger, and one can jump backwards
and look at the state of the program where this logged event was recorded
(granted, full program-state recording could cost a lot of extra memory
and/or be problematic on a conventional OS, say Windows, likely requiring
some level of virtualization).

partial capture though, such as stacktraces, could be useful (as well as the
ability to show/hide certain types of log events...).


or such...
 
J

Jorgen Grahn

.
I usually use a debugger if something is crashing somewhere or going
horridly wrong (or if I really can't figure out the problem from the source
or the logs).

I usually use logs for everything which looks out of place or may be useful
to note (just I prefer to keep common events out of the logs, as it is kind
of a hassle trying to find the cause of a bug when sifting through 10,000
open and close file messages).

sometimes, it would be nice to know the backtraces for logged events, but
these are awkward to gain and would waste a lot of space in the logs...

maybe a hybrid of a typical debugger and a log tool would be nice, where log
events are noted and captured by the debugger, and one can jump backwards
and look at the state of the program where this logged event was recorded

I've used such a system once, and there are probably people here who
use such a thing regularly.

Can't remember the name. Was possibly German. Hardware, attach to
your embedded ARM system using JTAG. Break/crash somewhere and step
backwards through program *state* to the point where you messed up
(or its circular state buffer ran out).

Horrible user interface, and since it was expensive most people
didn't get enough runtime to learn to use it efficiently. But the
time machine effect was cool. I saw at least one guy do magic with
it -- I was complaining about a crash in a subsystem, and he showed
me the real problem -- a stack overrun I'd created myself.
(granted, full program-state recording could cost a lot of extra memory
and/or be problematic on a conventional OS, say Windows, likely requiring
some level of virtualization).

Possibly it could be implemented inside valgrind, but it would need a
very complex user interface, and performance would suck.

/Jorgen
 
J

Jorgen Grahn

Why the surprise? One argument follows a differeent path.


Yes.

It's worth pointing out here that valgrind can show you "you leaked N
bytes in M blocks, and they were allocated by this line of code". It
seems to me the OP didn't enable that pretty obvious option, because
he doesn't cite that output.

/Jorgen
 
I

Ian Collins

.

I've used such a system once, and there are probably people here who
use such a thing regularly.

Can't remember the name. Was possibly German. Hardware, attach to
your embedded ARM system using JTAG. Break/crash somewhere and step
backwards through program *state* to the point where you messed up
(or its circular state buffer ran out).

Lauterbach?
 

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,954
Messages
2,570,114
Members
46,702
Latest member
VernitaGow

Latest Threads

Top