2

This is just a doubt which came into my mind

here is the code shown below

          main()
          {
                  int *p,*q;
                  int a =20;
                  p = q;
                  p = &a;
                  free(p);
                  printf("The values of p and q are %d and %d\n",*p,*q);
           }

My doubt is if we free the pointer p,the memory allocated for this pointer gets deallocated and is returned to the free pool of memory and so in this case since q is also pointing to p,dereferencing q should give error as per my understanding.Am i right in telling that?? i had run this program in dev C++ compiler and to my surprise it is showing the values for both the pointers. Do we call the pointer q as the dangling pointer in this case?

thanks a lot in advance Maddy

sarnold
  • 102,305
  • 22
  • 181
  • 238
Maddy
  • 503
  • 4
  • 12
  • 21

7 Answers7

4

Attempting to free p here invokes undefined behavior - you're only allowed to free what you malloc (or calloc, or realloc, or strdup). In this case, you're free-ing a pointer to a stack variable, a, which is not allowed.

The same applies to dereferencing *q - the value in q is uninitialized, so dereferencing it causes undefined behavior as well. Strictly speaking, p = q is undefined* as well, but in practice simply copying the value of an uninitialized variable tends not to cause too much of a problem in and of itself (just don't expect the value to be meaningful).

When you invoke undefined behavior, anything can happen - this includes, but is not limited to:

  • Crashing right away
  • Crashing later in some unrelated code
  • Corrupting some data without crashing
  • Corrupting some data on disk that you thought was safe
  • Contacting your backup server and corrupting the backups too
  • Allowing the hacker who triggered the bug control over your computer
  • Summoning demons through your nasal passages
  • Any combination of the above
  • On occasion, nothing at all.

The compiler is not required to give any sort of helpful error message, although it may do so in some cases.

In short, don't do it, but don't expect it to break in any one particular way if you do. These kinds of things have a funny way of breaking in a way that looks like bugs in a completely different part of your code.

* - per C99 6.2.6.1, if the C implementation has trap representations for pointer types, it is possible for the unspecified initial value for a variable to be a trap representation, at which point reading it via the q lvalue invokes undefined behavior.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
bdonlan
  • 224,562
  • 31
  • 268
  • 324
1

How can you free memory from the stack?

Does not compute!

leppie
  • 115,091
  • 17
  • 196
  • 297
  • @leppie...Free should actually free the memory pointed by p .So when u derefernce q,it should give error right?Please coirrect me if i am wrong – Maddy Jan 21 '11 at 08:59
  • @Maddy: `free` only frees memory allocated by `malloc`. – leppie Jan 21 '11 at 09:12
1

You should read about pointers and understand them better. Advice

p = q

q is an uninitialized pointer, you are assigning p to point to the same unspecified memory zone.

p = &a;

This is okay, now p contains the address of a but q remains uninitialized

free(p);

a is stored in the stack, not the heap. Could could have done this with :

int *a = malloc(sizeof(int)); // allocates memory and stores location
*a = 20;                      // modifies allocated memory
p = a;                        // have a second pointer to the same zone
free(p);                      // frees the allocated memory: now dereferencing either p or a is a sin.
Community
  • 1
  • 1
Benoit
  • 76,634
  • 23
  • 210
  • 236
0

You try to call free() on a pointer to a stack-allocated memory and that's undefined behavior, don't ever do that. Only call free() on pointers obtained from malloc().

sharptooth
  • 167,383
  • 100
  • 513
  • 979
0

a is an automatic variable, and applyinf free(p) where p=&a is an error, that you probably face up as soon you malloc other memory, since you mark as a free block memory that is not usable.

Felice Pollano
  • 32,832
  • 9
  • 75
  • 115
0

Trying to free memory that was not acquired with malloc, calloc, or realloc leads to UNDEFINED RESULTS. Sometimes it does something stupid like continuing to run and giving you silly results. Somtimes it does something more useful:

$ ./a.out
*** glibc detected *** ./a.out: munmap_chunk(): invalid pointer: 0x00007fff8393bd5c ***
======= Backtrace: =========
/lib/libc.so.6(+0x774b6)[0x7f7a30bc04b6]
./a.out[0x400526]
/lib/libc.so.6(__libc_start_main+0xfe)[0x7f7a30b67d8e]
./a.out[0x400439]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:03 675233                             /tmp/a.out
00600000-00601000 r--p 00000000 08:03 675233                             /tmp/a.out
00601000-00602000 rw-p 00001000 08:03 675233                             /tmp/a.out
00f04000-00f25000 rw-p 00000000 00:00 0                                  [heap]
7f7a30933000-7f7a30948000 r-xp 00000000 08:03 228559                     /lib/libgcc_s.so.1
7f7a30948000-7f7a30b47000 ---p 00015000 08:03 228559                     /lib/libgcc_s.so.1
7f7a30b47000-7f7a30b48000 r--p 00014000 08:03 228559                     /lib/libgcc_s.so.1
7f7a30b48000-7f7a30b49000 rw-p 00015000 08:03 228559                     /lib/libgcc_s.so.1
7f7a30b49000-7f7a30cc3000 r-xp 00000000 08:03 228962                     /lib/libc-2.12.1.so
7f7a30cc3000-7f7a30ec2000 ---p 0017a000 08:03 228962                     /lib/libc-2.12.1.so
7f7a30ec2000-7f7a30ec6000 r--p 00179000 08:03 228962                     /lib/libc-2.12.1.so
7f7a30ec6000-7f7a30ec7000 rw-p 0017d000 08:03 228962                     /lib/libc-2.12.1.so
7f7a30ec7000-7f7a30ecc000 rw-p 00000000 00:00 0                      
7f7a30ecc000-7f7a30eec000 r-xp 00000000 08:03 228501                     /lib/ld-2.12.1.so
7f7a310cc000-7f7a310cf000 rw-p 00000000 00:00 0
7f7a310ea000-7f7a310ec000 rw-p 00000000 00:00 0                      
7f7a310ec000-7f7a310ed000 r--p 00020000 08:03 228501                     /lib/ld-2.12.1.so
7f7a310ed000-7f7a310ee000 rw-p 00021000 08:03 228501                     /lib/ld-2.12.1.so
7f7a310ee000-7f7a310ef000 rw-p 00000000 00:00 0                      
7fff8391d000-7fff8393e000 rw-p 00000000 00:00 0                          [stack]
7fff839df000-7fff839e0000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted

My C library helpfully gives me the address that failed, and very helpfully dumps the memory map (which is new to me! thanks!) which lets me see quickly that the address is on the stack.

sarnold
  • 102,305
  • 22
  • 181
  • 238
  • Incidentally, a very rough search of an old copy of the cve.mitre.org database shows something like 60 vulnerabilities in software due to use-after-free and double-free bugs, and perhaps another 4 free(NULL) bugs leading to vulnerabilities. Please make sure you understand the correct use of `malloc()` and `free()`. – sarnold Jan 21 '11 at 09:05
0

This gives me the exact behavior that I expected when run through Valgrind:

==8839== Invalid free() / delete / delete[]
==8839==    at 0x4024836: free (vg_replace_malloc.c:325)
==8839==    by 0x8048440: main (boom.c:10)
==8839==  Address 0xbe9a5164 is on thread 1's stack

I did it because I was curious, as several were reporting the same behavior.

The address of p (as dereferenced by free()) is what is known as a dangling pointer, thus any operation on it is undefined. I compiled without optimization (-O0) and with debugging symbols (-g) to produce a better illustration, but it blows up no matter what.

Running the program normally just produces a segmentation fault, as expected. The program actually completes when profiled under valgrind (additional complaints when printf() also dereferences the explosive pointer):

==8839== Use of uninitialised value of size 4
==8839==    at 0x8048445: main (boom.c:11)
==8839==
The values of p and q are 20 and 459916161
==8839==
==8839== HEAP SUMMARY:
==8839==     in use at exit: 0 bytes in 0 blocks
==8839==   total heap usage: 0 allocs, 1 frees, 0 bytes allocated

But only because Valgrind is catching the SEGV.

Undefined behavior is just that, undefined. It is one of the leading causes of the dreaded "wow, works on my machine!" bug :)

Tim Post
  • 33,371
  • 15
  • 110
  • 174