2

What exactly is happening when I call free(a)? I know it is freeing the memory used, but does this also mean that the data stored in array a can no longer be accessed (therefore, not being able to call copyArray)?

int *a = (int *) malloc(sizeof(int) * numberOfInts);
for (i = 0; i < numberOfInts; i++) {
        a[i] = random();
        printf("%d\n", a[i]);
    }
    free(a);
    copyArray(*a++, numberOfInts);
Jamal
  • 763
  • 7
  • 22
  • 32
user1889966
  • 165
  • 1
  • 4
  • 11
  • 4
    You don't need to cast the return value of `malloc()` in a C program. – Carl Norum Feb 20 '13 at 17:53
  • http://www.cplusplus.com/reference/cstdlib/free/ – Josh Petitt Feb 20 '13 at 17:53
  • 1
    @CarlNorum Eh, not true. You **must not** cast the return value of `malloc()` in a C program. :P –  Feb 20 '13 at 17:53
  • I don't know about 'must not'. If you wanted to stick it in a `uintptr_t` for example, you'd need to. It's just not idiomatic. There's certainly nothing totally disastrous about it. – Carl Norum Feb 20 '13 at 17:54
  • @CarlNorum [There is.](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc/605858#605858) –  Feb 20 '13 at 17:55
  • Oh it certainly *can* cause an error. That doesn't mean that it *does* cause an error. – Carl Norum Feb 20 '13 at 17:58
  • 1
    @CarlNorum Sure, I wasn't saying it either. –  Feb 20 '13 at 18:02

7 Answers7

4

What exactly is happening when I call free(a)?

This is implementation specific. As an example, with Linux and glibc, one of several things can happen:

If the memory was allocated in a block of 128k or more, glibc will have allocated a new memory area (specifically, a copy-on-write mmap of /dev/zero). When it's freed, the memory area is simply deallocated (munmap'd)and disappears. Further accesses will crash.

If the allocated memory was smaller, it will go on the heap. The heap is a single memory area starting at a fixed address, and is of a size that the process can shrink or increase (with sbrk).

The memory allocator keeps tracks of which pieces of this area is allocated. The first time something is allocated, the size of heap is increased, and the memory is appended to the end in this new space.

If you free such a block of memory, at the end of the heap, the heap size can be reduced, thus making the memory invalid and making further accesses crash. The allocator will not increase or decrease the heap size for just a few bytes though, so at that point it depends on the size of the allocation and the number of blocks freed. It might be accessible, and it might not be.

If you allocate ten blocks of memory and free the first nine, you end up with an unused area in the heap. Since you can only modify the heap size by setting the end address, you can't really do anything about it. The memory is still valid, and accessing it will still work. You will probably even find your original data in it, and will be able to continue as if nothing happened.

However, as new memory is allocated, malloc will try to put it in this unused area, thus letting other data overwrite what was originally there. Setting an int in your free'd array could then overwrite a pointer in a completely unrelated part of your program, and hilarity and debugging ensues.

tl;dr: Don't access free'd memory!

that other guy
  • 116,971
  • 11
  • 170
  • 194
1

Yes, that's exactly what it means. As soon as you call free() the memory in question is returned for use by the operating system. It might still look like it's working, but you're causing undefined behaviour.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
1

You should not access the memory locations that are freed. Yes, the data stored in those locations can no longer be accessed. But accessing freed locations leads to undefined behavior.

Mahesh
  • 34,573
  • 20
  • 89
  • 115
1

but does this also mean that the data stored in array a can no longer be accessed

Yes - more precisely, accessing it (i. e. dereferencing an invalid pointer) results in undefined behavior, so your program can do anything (including crashing, that it probably will).

  • Or undefined behavior could mean launching missiles, as someone used to say -- maybe it was Scott Knaster. – minopret Feb 20 '13 at 17:53
  • @Mahesh: Not sure about that. But UB includes installing Zeus malware on your system and identity frauding you out of your house and all of your worldly posessions. – SecurityMatt Feb 20 '13 at 18:41
0

When the memory is freed you cannot make any assumption to what it might contain. So you should not access it anymore.

Emanuele Paolini
  • 9,912
  • 3
  • 38
  • 64
0

When you call free(a) it means that the memory has been flagged for re-use. So, writing an array to a will still work, but it is undefined behavior. Chances are it will be overwritten later without you being notified about it.

Secondly do not cast the return value of malloc() in C.

do this:

int *a = malloc(sizeof(*a) * numberOfInts);

Also, in C99, you have the provision for VLAs in which you can do this:

printf("Enter array length: ");
scanf("%d",&numberOfInts);
int a[numberOfInts];

and you will not have to manually de-allocate these arrays. Note however, there is a limit to the length you can have for VLAs

Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
  • Your "do this" should really be `malloc(sizeof(*a) * numberOfInts);` instead, if we wanna be super-safe. –  Feb 20 '13 at 17:55
  • @H2CO3: If you want to be super-safe, you probably want to check that multiplication for an integer overflow :/ – SecurityMatt Feb 20 '13 at 18:42
0

When you are using 'malloc', you are dynamically allocating a block of memory pointed at by a. Typically, although implementation specific, dynamically allocated memory is stored on the heap. Without calling free, you will be leaking memory when a goes out of scope.

The block of memory that you created, which is pointed at by a, can no longer be used after a call to free. This would have very unpredictable behaviour and could potentially cause a segmentation fault.

ed_me
  • 3,338
  • 2
  • 24
  • 34