-1

For example:

void heaptest(){
       int *a;
       a=(int*)malloc(1024*4);  
       int i=1024;
       while(i--){      
                  *a=i;
                  //printf("%d",*a);
                   a++;
                 }
       free(a);
                }

When the 'a' was used as a pointer, assume it points to address "0x20000". And the scope of this heap area is from 0x20000 to 0x21000. totally 4096 bytes.

after the while loop, the 'a' was pointed to 0x21004, which is actually out of the scope of the defined heap. if we free the heap using

free(a)

Will this heap be freed successfully?

For my observation, when I use this func in Visual Studio. it will show

Invalid address specified to RtlValidateHeap

and the value of a is 0x21004 before the free() operation whenever whether there is a printf() function in the while loop.

When I use this function on Keil-MDK for STM32F7(Cortex M7), it shows nothing but before the free operation. the value of 'a' will become 0x00000;

But when I add the printf() function shown in the code. the value of 'a' will back to the initial value 0x20000.

So, the final question is, could we change the value of the heap pointer? or assign it back to the initial value every time before the free() operation?

  • 1
    change that to `a=malloc(1024*sizeof(int));` – yano Jul 28 '17 at 15:45
  • One of the worst long questions I have ever seen here. It only shows lack of the elementary OP knowledge. If I was him I would immediately delete it. – 0___________ Jul 28 '17 at 18:38
  • And buy a beginners C book. – 0___________ Jul 28 '17 at 18:43
  • You badly need to double-check what `free` does. It doesn't magically know where the beginning of the block is if you give it a pointer in the middle. From [the standard](http://port70.net/~nsz/c/c11/n1570.html#7.22.3.3): "if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined." I'll let you figure out precisely what that means. – Nic Jul 29 '17 at 03:10

4 Answers4

3

Will this heap be freed successfully?

It is impossible to say. You invoke undefined behavior by passing a pointer value to free() that was not returned by malloc() or one of the other allocation functions. That could turn out to manifest as freeing the block into which the pointer points, but more likely it produces an error, or worse: silent memory corruption.

Note in particular that it is the pointer value that matters. The variable, if any, in which you store the pointer value has nothing directly to do with it.

could we change the value of the heap pointer?

In the sense that the pointer is a value, no, you can no more change it than you can change the value 1. But you can cause a variable in which that value is stored to instead contain a different value. You may even be able to do so in a way that allows you to recover the original value, so as to retain the ability to free the allocated memory.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
1

You need to free the address your were given. What you do to the code's variables in between does not matter.

This is valid:

char * p = malloc(42);
p++;
p--;
free(p);

This as well:

char * p = malloc(42);
char * q = p:
/* p += 43; */ /* Invokes UB, as making q point more then just one past the object. */
q += 42; /* Just one past the allocated memory. */
q -= 42;
free(q);

This isn't

char * p = malloc(42);
p++;
free(p);

This neither:

char * p = malloc(42);
p--;
free(p);
alk
  • 69,737
  • 10
  • 105
  • 255
0

An address passed to free must have been obtained as the return value of malloc/calloc/etc. Passing any other pointer invokes undefined behavior.

From the MSDN page for free:

The free function deallocates a memory block (memblock) that was previously allocated by a call to calloc, malloc, or realloc. The number of freed bytes is equivalent to the number of bytes requested when the block was allocated (or reallocated, in the case of realloc). If memblock is NULL, the pointer is ignored and free immediately returns. Attempting to free an invalid pointer (a pointer to a memory block that was not allocated by calloc, malloc, or realloc) may affect subsequent allocation requests and cause errors.

Keep track of the original pointer so you can later pass it to free:

void heaptest(){
       int *a, a_sav;
       a=(int*)malloc(1024*4);  
       a_sav = a;  // save the original pointer
       int i=1024;
       while(i--){      
           *a=i;
           printf("%d",*a);
           a++;
       }
       free(a_sav);  // free the saved pointer
}
dbush
  • 205,898
  • 23
  • 218
  • 273
0

Calling free with an argument that does not point to an adress allocated via malloc, calloc or realloc is undefined behavior. You have absolutely zero information on what it will do. Try something in this form.

void heaptest(){
    // Declare a const to make sure we free the right adress in the end
    int * const a = (int*)malloc(1024*size_of(int));  
    int i=1024;
    do {
        // This will loop from a[0] to a[1024] which is what I assume you meant to do
        a[1024-i] = i;
    } while (--i);
    free(a);
    }

It's hard to say if this program does what you wanted. You can change i or the index or the right hand side of the assignment to suit your needs but don't do the loop like you did because it's way more error-prone.

patatahooligan
  • 3,111
  • 1
  • 18
  • 27