[SOLVED] free freeing data twice or data that shoulnd't be freed
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
$ gcc -g crash.c && valgrind ./a.out
crash.c: In function ‘main’:
crash.c:78:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
crash.c:79:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
==5524== Memcheck, a memory error detector
==5524== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==5524== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==5524== Command: ./a.out
==5524==
==5524== Invalid write of size 1
==5524== at 0x40091E: main (crash.c:31)
==5524== Address 0x51f1041 is 0 bytes after a block of size 1 alloc'd
==5524== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5524== by 0x40090B: main (crash.c:30)
==5524==
==5524== Invalid read of size 4
==5524== at 0x4EA10EE: fgets (iofgets.c:52)
==5524== by 0x400968: main (crash.c:36)
==5524== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==5524==
==5524==
==5524== Process terminating with default action of signal 11 (SIGSEGV)
==5524== Access not within mapped region at address 0x0
==5524== at 0x4EA10EE: fgets (iofgets.c:52)
==5524== by 0x400968: main (crash.c:36)
==5524== If you believe this happened as a result of a stack
==5524== overflow in your program's main thread (unlikely but
==5524== possible), you can try to increase the size of the
==5524== main thread stack using the --main-stacksize= flag.
==5524== The main thread stack size used in this run was 8388608.
Error opening hometown.map
==5524==
==5524== HEAP SUMMARY:
==5524== in use at exit: 1 bytes in 1 blocks
==5524== total heap usage: 2 allocs, 1 frees, 569 bytes allocated
==5524==
==5524== LEAK SUMMARY:
==5524== definitely lost: 0 bytes in 0 blocks
==5524== indirectly lost: 0 bytes in 0 blocks
==5524== possibly lost: 0 bytes in 0 blocks
==5524== still reachable: 1 bytes in 1 blocks
==5524== suppressed: 0 bytes in 0 blocks
==5524== Rerun with --leak-check=full to see details of leaked memory
==5524==
==5524== For counts of detected and suppressed errors, rerun with: -v
==5524== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2)
Okay, we have invalid write on line 31:
Code:
ch = malloc(1);
ch[1] = '\0'; // line 31
This bug has already been discovered by ntubski. And we will see that the same error occurs two more times in the program. You allocated only one byte for ch, but on the next line (N31) you try to assign zero value to the second element of string ch. C uses zero-based indexing: first element has index 0, second element -- 1 etc. So to fix this bug you should write
Code:
ch = malloc(1);
ch[0] = '\0'; // line 31
(BTW why you use one-character dynamic string here instead of just char ch;?)
Fixed.
Repeat the procedure:
Code:
$ gcc -g crash.c && valgrind ./a.out
crash.c: In function ‘main’:
crash.c:78:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
crash.c:79:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
==5568== Memcheck, a memory error detector
==5568== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==5568== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==5568== Command: ./a.out
==5568==
==5568== Invalid read of size 4
==5568== at 0x4EA10EE: fgets (iofgets.c:52)
==5568== by 0x400964: main (crash.c:36)
==5568== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==5568==
==5568==
==5568== Process terminating with default action of signal 11 (SIGSEGV)
==5568== Access not within mapped region at address 0x0
==5568== at 0x4EA10EE: fgets (iofgets.c:52)
==5568== by 0x400964: main (crash.c:36)
==5568== If you believe this happened as a result of a stack
==5568== overflow in your program's main thread (unlikely but
==5568== possible), you can try to increase the size of the
==5568== main thread stack using the --main-stacksize= flag.
==5568== The main thread stack size used in this run was 8388608.
Error opening hometown.map
==5568==
==5568== HEAP SUMMARY:
==5568== in use at exit: 1 bytes in 1 blocks
==5568== total heap usage: 2 allocs, 1 frees, 569 bytes allocated
==5568==
==5568== LEAK SUMMARY:
==5568== definitely lost: 0 bytes in 0 blocks
==5568== indirectly lost: 0 bytes in 0 blocks
==5568== possibly lost: 0 bytes in 0 blocks
==5568== still reachable: 1 bytes in 1 blocks
==5568== suppressed: 0 bytes in 0 blocks
==5568== Rerun with --leak-check=full to see details of leaked memory
==5568==
==5568== For counts of detected and suppressed errors, rerun with: -v
==5568== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)
What's wrong with line 36:
Code:
fgets(name, 100, fp);
? Looks good. But couple of lines above we see
Code:
if ((fp = fopen(".hometown.map", "r")) == NULL)
printf("Error opening hometown.map\r\n");
And we also see your error message "Error opening hometown.map". There are no such file as ".hometown.map" in my /tmp directory, naturally. The program tells us that there are no such file and just continues execution! Not good!
Code:
if ((fp = fopen(".hometown.map", "r")) == NULL) {
printf("Error opening hometown.map\r\n");
free(ch); // to calm down valgrind
exit(EXIT_FAILURE);
}
Fixed.
Continue:
Code:
$ touch .hometown.map
$ gcc -g crash.c && valgrind ./a.out
crash.c: In function ‘main’:
crash.c:81:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
crash.c:82:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
==5610== Memcheck, a memory error detector
==5610== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==5610== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==5610== Command: ./a.out
==5610==
==5610== Invalid write of size 8
==5610== at 0x400B72: main (crash.c:68)
==5610== Address 0x51f1318 is 0 bytes after a block of size 8 alloc'd
==5610== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610== by 0x400B06: main (crash.c:63)
==5610==
==5610== Invalid read of size 8
==5610== at 0x400BAE: main (crash.c:69)
==5610== Address 0x51f1318 is 0 bytes after a block of size 8 alloc'd
==5610== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610== by 0x400B06: main (crash.c:63)
==5610==
==5610== Invalid read of size 8
==5610== at 0x400BC4: main (crash.c:70)
==5610== Address 0x51f1318 is 0 bytes after a block of size 8 alloc'd
==5610== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610== by 0x400B06: main (crash.c:63)
==5610==
==5610== Invalid write of size 1
==5610== at 0x400BFC: main (crash.c:70)
==5610== Address 0x51f1364 is 0 bytes after a block of size 4 alloc'd
==5610== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610== by 0x400B67: main (crash.c:68)
==5610==
==5610== Invalid write of size 8
==5610== at 0x400C45: main (crash.c:72)
==5610== Address 0x51f1320 is 8 bytes after a block of size 8 alloc'd
==5610== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610== by 0x400B06: main (crash.c:63)
==5610==
==5610== Invalid read of size 8
==5610== at 0x400C87: main (crash.c:73)
==5610== Address 0x51f1320 is 8 bytes after a block of size 8 alloc'd
==5610== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610== by 0x400B06: main (crash.c:63)
==5610==
==5610== Invalid read of size 8
==5610== at 0x400C9D: main (crash.c:74)
==5610== Address 0x51f1320 is 8 bytes after a block of size 8 alloc'd
==5610== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610== by 0x400B06: main (crash.c:63)
==5610==
==5610== Invalid write of size 1
==5610== at 0x400CD8: main (crash.c:74)
==5610== Address 0x51f13b5 is 0 bytes after a block of size 5 alloc'd
==5610== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610== by 0x400C3A: main (crash.c:72)
==5610==
==5610== Invalid read of size 8
==5610== at 0x400D27: main (crash.c:79)
==5610== Address 0x51f1318 is 0 bytes after a block of size 8 alloc'd
==5610== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610== by 0x400B06: main (crash.c:63)
==5610==
==5610== Conditional jump or move depends on uninitialised value(s)
==5610== at 0x4E7D3D1: vfprintf (vfprintf.c:1630)
==5610== by 0x4E858F8: printf (printf.c:35)
==5610== by 0x400D3F: main (crash.c:79)
==5610==
==5610== Invalid read of size 8
==5610== at 0x400D47: main (crash.c:80)
==5610== Address 0x51f1320 is 8 bytes after a block of size 8 alloc'd
==5610== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610== by 0x400B06: main (crash.c:63)
==5610==
==5610== Conditional jump or move depends on uninitialised value(s)
==5610== at 0x4E7D3D1: vfprintf (vfprintf.c:1630)
==5610== by 0x4E858F8: printf (printf.c:35)
==5610== by 0x400D5F: main (crash.c:80)
==5610==
==5610== Invalid read of size 8
==5610== at 0x400DEE: main (crash.c:83)
==5610== Address 0x51f1320 is 8 bytes after a block of size 8 alloc'd
==5610== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610== by 0x400B06: main (crash.c:63)
==5610==
==5610== Invalid read of size 8
==5610== at 0x400E0B: main (crash.c:85)
==5610== Address 0x51f1318 is 0 bytes after a block of size 8 alloc'd
==5610== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610== by 0x400B06: main (crash.c:63)
==5610==
top->width = -1
top->height = 0
top->name = NUL
top->description = NULL
length of name: 3
length of desc: 4
descr freed
name freed
top freed
==5610==
==5610== HEAP SUMMARY:
==5610== in use at exit: 0 bytes in 0 blocks
==5610== total heap usage: 5 allocs, 5 frees, 586 bytes allocated
==5610==
==5610== All heap blocks were freed -- no leaks are possible
==5610==
==5610== For counts of detected and suppressed errors, rerun with: -v
==5610== Use --track-origins=yes to see where uninitialised values come from
==5610== ERROR SUMMARY: 14 errors from 14 contexts (suppressed: 2 from 2)
Oh no, not again..
Line 68:
Code:
top->name = malloc(strlen(name) + 1);
Can we write to top->name? Did we allocated space for it?
Code:
top = malloc(sizeof(top));
Hmm.. Yes? NO! What is top?
Code:
struct areas *top;
It is a pointer, its size is something like 4 or 8 bytes. Hardly enough.. One should write
Code:
top = malloc(sizeof(struct areas));
Fixed.
Continue:
Code:
$ gcc -g crash.c && valgrind ./a.out
crash.c: In function ‘main’:
crash.c:81:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
crash.c:82:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
==5866== Memcheck, a memory error detector
==5866== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==5866== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==5866== Command: ./a.out
==5866==
==5866== Invalid write of size 1
==5866== at 0x400BFC: main (crash.c:70)
==5866== Address 0x51f1374 is 0 bytes after a block of size 4 alloc'd
==5866== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5866== by 0x400B67: main (crash.c:68)
==5866==
==5866== Invalid write of size 1
==5866== at 0x400CD8: main (crash.c:74)
==5866== Address 0x51f13c5 is 0 bytes after a block of size 5 alloc'd
==5866== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5866== by 0x400C3A: main (crash.c:72)
==5866==
==5866== Conditional jump or move depends on uninitialised value(s)
==5866== at 0x4E7D3D1: vfprintf (vfprintf.c:1630)
==5866== by 0x4E858F8: printf (printf.c:35)
==5866== by 0x400D3F: main (crash.c:79)
==5866==
==5866== Conditional jump or move depends on uninitialised value(s)
==5866== at 0x4E7D3D1: vfprintf (vfprintf.c:1630)
==5866== by 0x4E858F8: printf (printf.c:35)
==5866== by 0x400D5F: main (crash.c:80)
==5866==
top->width = -1
top->height = 0
top->name = NUL
top->description = NULL
length of name: 3
length of desc: 4
descr freed
name freed
top freed
==5866==
==5866== HEAP SUMMARY:
==5866== in use at exit: 0 bytes in 0 blocks
==5866== total heap usage: 5 allocs, 5 frees, 610 bytes allocated
==5866==
==5866== All heap blocks were freed -- no leaks are possible
==5866==
==5866== For counts of detected and suppressed errors, rerun with: -v
==5866== Use --track-origins=yes to see where uninitialised values come from
==5866== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 2 from 2)
$ gcc -g crash.c && valgrind ./a.out
crash.c: In function ‘main’:
crash.c:81:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
crash.c:82:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
==5915== Memcheck, a memory error detector
==5915== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==5915== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==5915== Command: ./a.out
==5915==
top->width = -1
top->height = 0
top->name = NUL
top->description = NULL
length of name: 3
length of desc: 4
descr freed
name freed
top freed
==5915==
==5915== HEAP SUMMARY:
==5915== in use at exit: 0 bytes in 0 blocks
==5915== total heap usage: 5 allocs, 5 frees, 610 bytes allocated
==5915==
==5915== All heap blocks were freed -- no leaks are possible
==5915==
==5915== For counts of detected and suppressed errors, rerun with: -v
==5915== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
I'm sorry I didn't include .hometown.map I thought I gave you everything you needed to debug and I myself
came up short. I must say I am much oblidged to you, Firstfire. top = malloc(sizeof(struct areas));
was exactly the problem. everything else is actually really cool.
Again thanks to Firstfire. I read it fifteen times and fifteen times I missed it.
And special thanks to Ntubski for pointing out my character.
Sharing my Cool skeleton project: http://o0oo0.net16.net/shared
I can't figure out what you are doing, linked-listing?
I think you are making life very difficult for yourself.
Why are you poncing about with malloc may I ask?
It's a recipe for mistakes avoid if you can.
If you must you can use strdup(3) to copy strings.
If it's a fire-and-forget application don't even waste your time calling free
the OS will recover any allocated space when you exit.
And don't do everything in one main function unless it's very trivial.
And I wouldn't use fread if I can get away with using stdio.h
(Let the OS do the work where you can and use your time for the interesting stuff).
well im using malloc because I can't get everything to compile right. I'm being difficult intentionally to master what I cannot do casually.
since you mention ddd maybe you can help me use it.
My program seems to be changing the address of char name[0] to 0x00. or I think because strlen of name = 0;
so how can I use ddd valgrind and gdb to find where the registry error is easily if I can. maybe you could show me an example use of ddd for this.
char area_map[10000][10000];
crashes my program
but when its not there the program runs great
If you search for other threads on "stack size" I'm sure you can easily find both an explanation of the cause of the crash, and several alternatives for making it work.
In the example in that post it is important that the call to increase the stack limit happens before the call to the function that includes the declaration of the large array. I think C99 allows you to declare the large array within a function after doing work, such as increasing the stack limit, earlier in the same function. That might work. With certain added tricks specific to C99, it could work reliably. But in most cases the compiler will move the stack allocation to the beginning of the function, so changing the limit earlier in the same function is not good enough. It needs to be changed in a different function executed before this function is called.
I expect you want that array declared in main() in some program similar to the one at the top of this thread. In C, that makes it very hard to execute code before the function is called. There are other methods, but I suggest you have too much code in main anyway. Consider moving almost everything from main to some other function called by main. I would tend to leave inside main certain steps like opening of required files (".hometown.map") and aborting if those files are missing, then pass the file pointer to the function that takes over most of main's previous job.
is that a stack problem or am I defining it wrong?
You are defining it wrong (or allocating it wrong). It is not a stack problem.
char **area_map together with area_map[y][x] implies area_map points to a vector of pointers and each of those points to a separately allocated vector of data. You could replace the single allocation step with multiple allocations to build up the space implied by your current declaration and access code. Alternately, you could change the declaration to fit your existing allocation and access:
In ANSI C, that method only works when the width is know at compile time (the height can still be decided at run time). The multi layered allocation lets both width and height be decided at run time. I think C99 and/or some gcc extension lets you use the declaration I suggested and still replace the 1001 with a variable. But I don't program in C99, so I might be confused on that detail.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.