0

Given the following line:

 int *digits = (int *) malloc(3 * sizeof(int));

Say we store the values 1, 2 and 3 in locations, digits[0], digits[1], digits[2]. As follows:

digits[0] = 1;
digits[1] = 2;
digits[2] = 3;

If the following line is called:

free(++digits);

Is the entire memory range returned by malloc freed, or just the int sized block currently pointed to by digits - at that time, digits[1]? Or is the correct way, to free the entire range by iteration, i.e:

for (i = 0; i < 3; i++)
{
    free(digits[i]);
}

I am trying to understand the range of a call to free. Is the entire memory chunk returned by malloc freed, or is only a sub-portion, currently referenced by the pointer digits freed?

hermetik
  • 115
  • 9
  • 1
    Welcome to Stack Overflow! [Please see this discussion on why not to cast the return value of `malloc()` and family in `C`.](http://stackoverflow.com/q/605845/2173917). – Sourav Ghosh Sep 30 '15 at 05:38

2 Answers2

6

You must free() the exact same pointer value you get from malloc(). The entire blob of memory allocated by malloc() will be freed at once.

You can't use a pointer int the middle of the buffer returned to you by malloc() to free() it, but you must pass to free() exactly what malloc() returned you.

http://linux.die.net/man/3/malloc is pretty explicit about this.

Russ Schultz
  • 2,545
  • 20
  • 22
  • Oh, and you can only free it once. Doing it again is undefined. Freeing a pointer that wasn't returned by a previous malloc is undefined. Do not anger the heap. It will treat you in most devious ways if you do. – Russ Schultz Sep 30 '15 at 02:26
  • When you say: "You can't point in the middle of it". Does that mean that the assignment statements `digits[0] = 1, digits[1] = 2, digits[2] = 3`, should not be used? – hermetik Sep 30 '15 at 02:28
  • 1
    I mean, you _can_ free a different pointer. It's just one of those "undefined behavior" scenarios, the kind where the language spec clearly allows the program to set your house on fire and kidnap your children. :-) More seriously, most `malloc` implementations are storing allocation metadata immediately *before* the pointer they return; if you pass an offset from the pointer to `free` it's going to interpret earlier parts of your allocation as the allocation metadata, when it most definitely is not, and this is how you come home to a charred ruin and a ransom note from the ISO C committee. – ShadowRanger Sep 30 '15 at 02:28
  • @crypitc You're guaranteed to be able to read/write from any address that is the returned from `malloc()`, plus the length requested. You can only pass to `free()` the value `malloc()` gave you. – Russ Schultz Sep 30 '15 at 02:31
  • 1
    The C standard is worded better than the linux manpage IMHO. "If ptr is a null pointer, no action occurs. Otherwise, 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." (sect 7.22.3.3 para 2) – rici Sep 30 '15 at 02:46
  • @rici you're right. I just took the first google hit that came up. – Russ Schultz Sep 30 '15 at 02:46
1

As per rule malloc provide you with chunk of memory you demanded and return you start address of the chunk. you have to use digit to free memory as the only legal way to identify the allocated memory is pointer returned in your case it is digits

incompetent
  • 1,715
  • 18
  • 29
  • you don't have to use `digits`. You can assign `digits` to any other thing, as long as the value returned by `malloc()` is passed to `free()`. Any pointer variable that contains the value returned by `malloc()` is fine. – Russ Schultz Sep 30 '15 at 02:29
  • yes if he assign to other thing but question is simple whether to use digit or ++digit. I try to answer in only that domain for clarity – incompetent Sep 30 '15 at 02:33