|
From: <eru...@ti...> - 2010-10-06 12:43:06
|
Hello all.
I'm just a noob linux programmer and am trying to debug a
complex application that gives me all sorts of errors.
Since i'm buried
deep in pointers I put up a stupid program just to play around with
pointers and valgrind's error reporting.
To understand things better.
The full source code is at the end of this email.
Lines 19, 20 and 22
are partially commented out.
If i use the full declaration, valgrind
reports this:
==4519== 16 bytes in 1 blocks are definitely lost in
loss record 1 of 6
==4519== at 0x4024F20: malloc (vg_replace_malloc.
c:236)
==4519== by 0x8048759: main (pointers.c:19)
==4519==
==4519== 16 bytes in 1 blocks are definitely lost in loss record 2 of 6
==4519== at 0x4024F20: malloc (vg_replace_malloc.c:236)
==4519==
by 0x8048769: main (pointers.c:20)
==4519==
==4519== 1,480 (40 direct,
1,440 indirect) bytes in 1 blocks are definitely lost in loss record 3
of 3
==4519== at 0x4024F20: malloc (vg_replace_malloc.c:236)
==4519== by 0x80486F9: main (pointers.c:22)
Which i don't
understand.
If I do not explicitly initialize the pointers, accessing
any element of the structure results in an error.
This should mean
(according to my knowledge and understanding) that the real structure
has not been allocated (which should be the case since only the pointer
has been initialized). But the valgrind report seems to say the
contrary.
If I comment the explicit declarations (like you find in the
source below) another error comes out
==4472== 160 (16 direct, 144
indirect) bytes in 1 blocks are definitely lost in loss record 4 of 5
==4472== at 0x4024F20: malloc (vg_replace_malloc.c:236)
==4472==
by 0x8048710: main (pointers.c:24)
I don't understand how is it
possibile to loose memory by allocating new pointers.
I loose if i
reallocate an already existing pointer, then the memory previously
pointed will be lost.
But what is this?
I have very big problems i
can't seem to pinpoint.
Let's start here and see if i can understand
them.
Thank you very much
Claudio Carbone
#include <stdlib.h>
#include <stdio.h>
typedef struct map_cell_vector {
int px;
int
py;
float distance;
struct map_cell_vector *next;
}
map_cell_vector;
void free_vector (map_cell_vector *ptr);
int main
(int argc, const char **argv) {
int i,j;
map_cell_vector *ptr1;
//=malloc (sizeof(map_cell_vector));
map_cell_vector *ptr2; //=malloc
(sizeof(map_cell_vector));
map_cell_vector *ptr3;
map_cell_vector
**array; // = (map_cell_vector**) malloc (10 * sizeof
(map_cell_vector*));
for (i=0;i<10;i++)
array[i]=malloc(sizeof
(map_cell_vector));
map_cell_vector *ptr4,*ptr5;
for (i=0;i<10;
i++){
ptr4=array[i];
ptr4->px=0+(10*i);
ptr4->py=0+(10*i);
for (j=1;j<10;j++) {
ptr5=(map_cell_vector*)malloc(sizeof
(map_cell_vector));
ptr4->next=ptr5;
ptr4=ptr5;
ptr4-
>px=j+(10*i);
ptr4->py=j+(10*i);
}
}
for
(i=0;i<10;i++) {
printf("Starting back trace of array[%d]: \n",i);
map_cell_vector *ptr6=array[i]->next;
printf("-->(%2d,%2d)",
array[i]->px,array[i]->py);
while (ptr6->next != NULL) {
printf("-->(%2d,%2d)",ptr6->px,ptr6->py);
ptr6=ptr6->next;
}
printf("-->(%2d,%2d)\n",ptr6->px,ptr6->py);
}
free_vector(array
[3]);
}
void free_vector (map_cell_vector *ptr) {
printf ("now
in (%d,%d)\n",ptr->px,ptr->px);
if (ptr->next != NULL) {
printf
("entering cell -> ");
free_vector(ptr->next);
}
printf
("\nfreeing cell (%d,%d)\n",ptr->px,ptr->px);
free(ptr);
}
|
|
From: David C. <dcc...@ac...> - 2010-10-06 18:18:20
|
Lines 19 and 20 are easy: you allocate memory, store a pointer to
those two memory blocks in ptr1 and ptr2, then never release them. You
could remove ptr1 and ptr2 from this program and it would otherwise
remain the same.
Line 22 is a little more complex. Here you allocate an array to hold
pointers. In lines 23 and 24 you fill the array with pointers. Each
pointer references a block of memory. A little below, you create singly
linked lists of records, each of which starts at an array entry.
At the end of your program you release one list of vectors. You do not
release every list of vectors, and you do not release the array. All of
the memory leaks in the full program (with everything uncommented)
should go away if you replace the line "free_vector(array[3]);" with:
free(ptr1);
free(ptr2);
for (i=0;i<10;i++)
free_vector(array[3]);
free(array);
A warning: the memory you get from malloc() is not initialized. Your
free_vector() function may try to access uninitialized memory when it
reads "ptr6->next". Look at the difference between malloc() and
calloc(). You don't have to use calloc(), but you should always
initialize all fields of every memory record you allocate. You're
initializing "px" and "py" but don't always initialize "ptr5->next"
(hint: you only initialize it if there is another iteration in the
loop; the last one is not initialized). Valgrind should be able to tell
you about this too.
You definitely need to spend some time learning about C pointers and
memory allocation. This little program is a good start; you should
understand it well before trying to debug your complex application.
On 10/6/2010 5:42 AM, eru...@ti... wrote:
> Hello all.
> I'm just a noob linux programmer and am trying to debug a
> complex application that gives me all sorts of errors.
> Since i'm buried
> deep in pointers I put up a stupid program just to play around with
> pointers and valgrind's error reporting.
> To understand things better.
>
> The full source code is at the end of this email.
> Lines 19, 20 and 22
> are partially commented out.
> If i use the full declaration, valgrind
> reports this:
>
> ==4519== 16 bytes in 1 blocks are definitely lost in
> loss record 1 of 6
> ==4519== at 0x4024F20: malloc (vg_replace_malloc.
> c:236)
> ==4519== by 0x8048759: main (pointers.c:19)
> ==4519==
>
> ==4519== 16 bytes in 1 blocks are definitely lost in loss record 2 of 6
>
> ==4519== at 0x4024F20: malloc (vg_replace_malloc.c:236)
> ==4519==
> by 0x8048769: main (pointers.c:20)
> ==4519==
> ==4519== 1,480 (40 direct,
> 1,440 indirect) bytes in 1 blocks are definitely lost in loss record 3
> of 3
> ==4519== at 0x4024F20: malloc (vg_replace_malloc.c:236)
>
> ==4519== by 0x80486F9: main (pointers.c:22)
>
> Which i don't
> understand.
> If I do not explicitly initialize the pointers, accessing
> any element of the structure results in an error.
> This should mean
> (according to my knowledge and understanding) that the real structure
> has not been allocated (which should be the case since only the pointer
> has been initialized). But the valgrind report seems to say the
> contrary.
> If I comment the explicit declarations (like you find in the
> source below) another error comes out
>
> ==4472== 160 (16 direct, 144
> indirect) bytes in 1 blocks are definitely lost in loss record 4 of 5
>
> ==4472== at 0x4024F20: malloc (vg_replace_malloc.c:236)
> ==4472==
> by 0x8048710: main (pointers.c:24)
>
> I don't understand how is it
> possibile to loose memory by allocating new pointers.
> I loose if i
> reallocate an already existing pointer, then the memory previously
> pointed will be lost.
> But what is this?
> I have very big problems i
> can't seem to pinpoint.
> Let's start here and see if i can understand
> them.
> Thank you very much
>
> Claudio Carbone
>
> #include<stdlib.h>
>
> #include<stdio.h>
>
>
>
> typedef struct map_cell_vector {
> int px;
> int
> py;
> float distance;
> struct map_cell_vector *next;
> }
> map_cell_vector;
>
>
> void free_vector (map_cell_vector *ptr);
>
> int main
> (int argc, const char **argv) {
> int i,j;
> map_cell_vector *ptr1;
> //=malloc (sizeof(map_cell_vector));
> map_cell_vector *ptr2; //=malloc
> (sizeof(map_cell_vector));
> map_cell_vector *ptr3;
> map_cell_vector
> **array; // = (map_cell_vector**) malloc (10 * sizeof
> (map_cell_vector*));
> for (i=0;i<10;i++)
> array[i]=malloc(sizeof
> (map_cell_vector));
>
> map_cell_vector *ptr4,*ptr5;
> for (i=0;i<10;
> i++){
> ptr4=array[i];
> ptr4->px=0+(10*i);
> ptr4->py=0+(10*i);
>
> for (j=1;j<10;j++) {
> ptr5=(map_cell_vector*)malloc(sizeof
> (map_cell_vector));
> ptr4->next=ptr5;
> ptr4=ptr5;
> ptr4-
>> px=j+(10*i);
> ptr4->py=j+(10*i);
>
>
> }
> }
> for
> (i=0;i<10;i++) {
> printf("Starting back trace of array[%d]: \n",i);
>
> map_cell_vector *ptr6=array[i]->next;
> printf("-->(%2d,%2d)",
> array[i]->px,array[i]->py);
> while (ptr6->next != NULL) {
>
> printf("-->(%2d,%2d)",ptr6->px,ptr6->py);
> ptr6=ptr6->next;
> }
>
> printf("-->(%2d,%2d)\n",ptr6->px,ptr6->py);
> }
> free_vector(array
> [3]);
>
>
> }
>
> void free_vector (map_cell_vector *ptr) {
> printf ("now
> in (%d,%d)\n",ptr->px,ptr->px);
> if (ptr->next != NULL) {
> printf
> ("entering cell -> ");
> free_vector(ptr->next);
> }
> printf
> ("\nfreeing cell (%d,%d)\n",ptr->px,ptr->px);
> free(ptr);
> }
>
>
>
>
> ------------------------------------------------------------------------------
> Beautiful is writing same markup. Internet Explorer 9 supports
> standards for HTML5, CSS3, SVG 1.1, ECMAScript5, and DOM L2& L3.
> Spend less time writing and rewriting code and more time creating great
> experiences on the web. Be a part of the beta today.
> http://p.sf.net/sfu/beautyoftheweb
> _______________________________________________
> Valgrind-users mailing list
> Val...@li...
> https://lists.sourceforge.net/lists/listinfo/valgrind-users
>
--
David Chapman dcc...@ac...
Chapman Consulting -- San Jose, CA
|
|
From: Claudio C. <eru...@ti...> - 2010-10-06 21:14:45
|
Thank you David for your answer.
I admit it's tough to follow all these pointers, but thanks to your
explanations I've been able to greatly reduce the number of errors in my
application.
At least I can now free almost all the memory I borrow!
But I'm still left mulling about freeing arrays of standard types.
I created a double array of ints this way:
int **occupancy_grid;
occupancy_grid = malloc (map_size_real.px * sizeof (int *));
for(i = 0; i < map_size_real.px; i++) {
occupancy_grid[i]=malloc (map_size_real.py * sizeof (int));
(and here I could point that I fail to understand the need for calloc when
malloc does the exact same thing...)
Anyway this way when I then attempt to free the single entries I have to do
this
for (i=0; i< map_size_real.px; i++)
for (j=0; j< map_size_real.py; j++)
free(& occupancy_grid[i][j]);
free(occupancy_grid);
this is understandable as I have to tell free() the area of memory to free
so I have to de-reference the pointer.
but the output is this
==6665== Invalid free() / delete / delete[]
==6665== at 0x4024B3A: free (vg_replace_malloc.c:366)
==6665== by 0x804884B: main (pointers.c:60)
==6665== Address 0x426635c is 0 bytes after a block of size 4 free'd
==6665== at 0x4024B3A: free (vg_replace_malloc.c:366)
==6665== by 0x804884B: main (pointers.c:60)
==6665==
==6665== Invalid free() / delete / delete[]
==6665== at 0x4024B3A: free (vg_replace_malloc.c:366)
==6665== by 0x804886C: main (pointers.c:61)
==6665== Address 0x4266358 is 0 bytes inside a block of size 4 free'd
==6665== at 0x4024B3A: free (vg_replace_malloc.c:366)
==6665== by 0x804884B: main (pointers.c:60)
==6665==
==6665==
==6665== HEAP SUMMARY:
==6665== in use at exit: 0 bytes in 0 blocks
==6665== total heap usage: 112 allocs, 212 frees, 1,720 bytes allocated
Lots more of frees then allocs, and errors in freeing which I can't
understand.
Probably it's the &occupancy_grid[i][j] which is wrong, but I do not
understand what should be done as using
free(occupancy_grid[i][j])
gives these
==6798== Conditional jump or move depends on uninitialised value(s)
==6798== at 0x4024AFA: free (vg_replace_malloc.c:366)
==6798== by 0x804884D: main (pointers.c:60)
==6798==
==6798== Invalid read of size 4
==6798== at 0x8048844: main (pointers.c:60)
==6798== Address 0x426635c is 0 bytes after a block of size 4 alloc'd
==6798== at 0x4024F20: malloc (vg_replace_malloc.c:236)
==6798== by 0x8048731: main (pointers.c:29)
==6798==
==6798== Invalid free() / delete / delete[]
==6798== at 0x4024B3A: free (vg_replace_malloc.c:366)
==6798== by 0x804884D: main (pointers.c:60)
==6798== Address 0x38 is not stack'd, malloc'd or (recently) free'd
==6798==
==6798==
==6798== HEAP SUMMARY:
==6798== in use at exit: 0 bytes in 0 blocks
==6798== total heap usage: 112 allocs, 132 frees, 1,720 bytes allocate
And the conditional jump reported doesn't even exist (at least not that I
can see at that line).
I know I'm missing something.
Thank you for the patience in helping me.
I once took a course in ansi c, but it's been time a long time ago :p
Regards
Claudio Carbone
source i'm using
#include <stdlib.h>
#include <stdio.h>
typedef struct map_cell_vector {
int px;
int py;
float distance;
struct map_cell_vector *next;
} map_cell_vector;
void free_vector (map_cell_vector *ptr);
int main (int argc, const char **argv) {
int i,j;
map_cell_vector **array = (map_cell_vector**) malloc (10 *
sizeof(map_cell_vector*));
for (i=0;i<10;i++)
array[i]=malloc(sizeof(map_cell_vector));
int **array2;
array2=malloc (10 * sizeof (int*));
for (i=0;i<10;i++)
array2[i]=malloc(sizeof(int));
map_cell_vector *ptr4,*ptr5;
for (i=0;i<10;i++){
ptr4=array[i];
ptr4->px=0+(10*i);
ptr4->py=0+(10*i);
for (j=1;j<10;j++) {
ptr5=(map_cell_vector*)malloc(sizeof(map_cell_vector));
ptr4->next=ptr5;
ptr4=ptr5;
ptr4->px=j+(10*i);
ptr4->py=j+(10*i);
}
}
for (i=0; i<10; i++) {
free_vector(array[i]);
for (j=0; j<10; j++)
free(array2[i][j]);
}
for (i=0; i<10; i++)
free(array2[i]);
free(array2);
free(array);
}
void free_vector (map_cell_vector *ptr) {
if (ptr->next != NULL) {
free_vector(ptr->next);
}
free(ptr);
}
|
|
From: David C. <dcc...@ac...> - 2010-10-06 23:43:26
|
Remember, you need one free() call for each malloc() or calloc()
call. You are creating a 2-D array using a set of distinct 1-D arrays.
occupancy_grid is an array of pointers to 1-D arrays. You allocate
occupancy_grid (and should release it at the end), then fill its entries
with pointers to allocated memory. To release it you would reverse the
process, freeing each 1-D array and then releasing occupancy_grid:
for(i = 0; i < map_size_real.px; i++)
free(occupancy_grid[i]);
free(occupancy_grid);
You don't release each individual element, because you didn't allocate
individual elements.
calloc() assigns 0 to every byte of memory allocated. This can save you
many lines of code to assign values to all values in a record. In your
original test program you had a map_cell_vector structure with four
fields. To avoid reading uninitialized memory, you can either use
calloc() to assign all bytes in a map_cell_vector structure to 0, or you
could use malloc() and then ensure that every field is initialized:
map_cell_vector *ptr = (map_cell_vector *)
malloc(sizeof(map_cell_vector));
ptr->px = some_calculation;
ptr->py = another_calculation;
ptr->distance = a_third_calculation;
ptr->next = NULL;
Your test program did not always assign values to the "distance" or
"next" fields. Although you never used the "distance" field, you did
reference the "next" field and so you risked trying to read memory that
you had not allocated.
On 10/6/2010 2:14 PM, Claudio Carbone wrote:
> Thank you David for your answer.
> I admit it's tough to follow all these pointers, but thanks to your
> explanations I've been able to greatly reduce the number of errors in my
> application.
> At least I can now free almost all the memory I borrow!
> But I'm still left mulling about freeing arrays of standard types.
> I created a double array of ints this way:
>
> int **occupancy_grid;
>
> occupancy_grid = malloc (map_size_real.px * sizeof (int *));
> for(i = 0; i< map_size_real.px; i++) {
> occupancy_grid[i]=malloc (map_size_real.py * sizeof (int));
>
> (and here I could point that I fail to understand the need for calloc when
> malloc does the exact same thing...)
> Anyway this way when I then attempt to free the single entries I have to do
> this
>
> for (i=0; i< map_size_real.px; i++)
> for (j=0; j< map_size_real.py; j++)
> free(& occupancy_grid[i][j]);
> free(occupancy_grid);
>
> this is understandable as I have to tell free() the area of memory to free
> so I have to de-reference the pointer.
> but the output is this
> ==6665== Invalid free() / delete / delete[]
> ==6665== at 0x4024B3A: free (vg_replace_malloc.c:366)
> ==6665== by 0x804884B: main (pointers.c:60)
> ==6665== Address 0x426635c is 0 bytes after a block of size 4 free'd
> ==6665== at 0x4024B3A: free (vg_replace_malloc.c:366)
> ==6665== by 0x804884B: main (pointers.c:60)
> ==6665==
> ==6665== Invalid free() / delete / delete[]
> ==6665== at 0x4024B3A: free (vg_replace_malloc.c:366)
> ==6665== by 0x804886C: main (pointers.c:61)
> ==6665== Address 0x4266358 is 0 bytes inside a block of size 4 free'd
> ==6665== at 0x4024B3A: free (vg_replace_malloc.c:366)
> ==6665== by 0x804884B: main (pointers.c:60)
> ==6665==
> ==6665==
> ==6665== HEAP SUMMARY:
> ==6665== in use at exit: 0 bytes in 0 blocks
> ==6665== total heap usage: 112 allocs, 212 frees, 1,720 bytes allocated
>
> Lots more of frees then allocs, and errors in freeing which I can't
> understand.
> Probably it's the&occupancy_grid[i][j] which is wrong, but I do not
> understand what should be done as using
>
> free(occupancy_grid[i][j])
>
> gives these
>
> ==6798== Conditional jump or move depends on uninitialised value(s)
> ==6798== at 0x4024AFA: free (vg_replace_malloc.c:366)
> ==6798== by 0x804884D: main (pointers.c:60)
> ==6798==
> ==6798== Invalid read of size 4
> ==6798== at 0x8048844: main (pointers.c:60)
> ==6798== Address 0x426635c is 0 bytes after a block of size 4 alloc'd
> ==6798== at 0x4024F20: malloc (vg_replace_malloc.c:236)
> ==6798== by 0x8048731: main (pointers.c:29)
> ==6798==
> ==6798== Invalid free() / delete / delete[]
> ==6798== at 0x4024B3A: free (vg_replace_malloc.c:366)
> ==6798== by 0x804884D: main (pointers.c:60)
> ==6798== Address 0x38 is not stack'd, malloc'd or (recently) free'd
> ==6798==
> ==6798==
> ==6798== HEAP SUMMARY:
> ==6798== in use at exit: 0 bytes in 0 blocks
> ==6798== total heap usage: 112 allocs, 132 frees, 1,720 bytes allocate
>
> And the conditional jump reported doesn't even exist (at least not that I
> can see at that line).
>
> I know I'm missing something.
> Thank you for the patience in helping me.
> I once took a course in ansi c, but it's been time a long time ago :p
>
> Regards
> Claudio Carbone
>
>
>
> source i'm using
>
>
> #include<stdlib.h>
> #include<stdio.h>
>
>
>
> typedef struct map_cell_vector {
> int px;
> int py;
> float distance;
> struct map_cell_vector *next;
> } map_cell_vector;
>
>
> void free_vector (map_cell_vector *ptr);
>
> int main (int argc, const char **argv) {
> int i,j;
> map_cell_vector **array = (map_cell_vector**) malloc (10 *
> sizeof(map_cell_vector*));
> for (i=0;i<10;i++)
> array[i]=malloc(sizeof(map_cell_vector));
> int **array2;
>
> array2=malloc (10 * sizeof (int*));
> for (i=0;i<10;i++)
> array2[i]=malloc(sizeof(int));
>
> map_cell_vector *ptr4,*ptr5;
> for (i=0;i<10;i++){
> ptr4=array[i];
> ptr4->px=0+(10*i);
> ptr4->py=0+(10*i);
> for (j=1;j<10;j++) {
> ptr5=(map_cell_vector*)malloc(sizeof(map_cell_vector));
> ptr4->next=ptr5;
> ptr4=ptr5;
> ptr4->px=j+(10*i);
> ptr4->py=j+(10*i);
>
>
> }
> }
>
> for (i=0; i<10; i++) {
> free_vector(array[i]);
> for (j=0; j<10; j++)
> free(array2[i][j]);
>
> }
> for (i=0; i<10; i++)
> free(array2[i]);
> free(array2);
> free(array);
>
> }
>
> void free_vector (map_cell_vector *ptr) {
> if (ptr->next != NULL) {
> free_vector(ptr->next);
> }
> free(ptr);
> }
>
>
> ------------------------------------------------------------------------------
> Beautiful is writing same markup. Internet Explorer 9 supports
> standards for HTML5, CSS3, SVG 1.1, ECMAScript5, and DOM L2& L3.
> Spend less time writing and rewriting code and more time creating great
> experiences on the web. Be a part of the beta today.
> http://p.sf.net/sfu/beautyoftheweb
> _______________________________________________
> Valgrind-users mailing list
> Val...@li...
> https://lists.sourceforge.net/lists/listinfo/valgrind-users
>
--
David Chapman dcc...@ac...
Chapman Consulting -- San Jose, CA
|