C Programming Questions

Hi guys I have a test in a week about C programming. I was wonder if you guys could explain stuff in more detail.

First of all is how does this work?

int i;
int *a = malloc(3 * sizeof (a));
for(i=0;i<3;i++){
a[i] = malloc(sizeof (**a));
a[i][0] =i;
}
free(a);
for(i=0;i<3;i++){
free(a[i]);
}

I am confused about calling free twice and why this works on my computer at least?

going through it, you have a point to an int, thats 3 ints big (so array of 3 ints)

then you have a loop that takes every a[i] and makes it a pointer to a.

then you delete the first pointer, and then the 3 pointers you made in the loops.

thats my guess at it.

technically the free(a) should be after the loop. It likely will never make a difference, but that is dependent on your OS and stdlib implementations, whether or not free() actually returns a page to the OS or simple keeps it in reserve.

Although I am slightly surprised that it does not crash...although I do suppose it would likely never crash on a 32-bit machine, or compiled for 32-bit, but the values returned by malloc [while valid unless NULL] are not decidable. while it is extremely unlikely they point to valid memory locations on a 64-bit system after everything has run, it is extremely unlikely.

@The_Space_Bear one thing you may not have noticed is that his typing is off. He declared a as a single pointer. "array"s don't truly exist in C, the syntax is just shorthand pointer arithmetic and dereferencing. Though he assigned enough memory for it to function, since a is declared as pointing to an integer and not another pointer, the pointer arithmetic would [typically] only increment 4 bytes when a pointer would require 8 byte offsets on a 64-bit system.

Often times malloc does it's own bookkeeping in memory adjacent to one or both sides of the returned value.

What would be correct is (note the type of a):
`
int i;
int *a = malloc(3sizeof(int*)); // doesnt point to an int, points to a pointer.
for(i = 0; i < 3; i++)
{
a[i] = malloc(sizeof(int)); // a[i] points directly to an int.
a[i][0] = i;
}

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

Now, if the question is about free, every malloc must have a corresponding call to free. If it does not, that is what is called a memory leak.

malloc dynamically allocates memory in a big, open, unstructured area of program memory called the heap. malloc itself does internal bookkeeping to keep track of what has NOT been allocated in the heap. This is typically a doubly linked list of memory blocks. When it allocates something, it also puts a tag on it (usually in the 8 bytes in front of the returned pointer) detailing what it did. free uses this tag to add the memory back to malloc's list.

I do not know if you are familiar with the halting problem, or undecidability in general, but malloc has no way to know what you are actually doing with the memory. So unless you explicitly call free, you are 'using' the memory, even if your program no longer has any references to it. Again, being undecidable, once you loose the reference, you can never know again where it pointed to use or to free, therefore malloc will consider it forever (being until your program exits) in use. Similarly, the OS has no way to know what you're doing with the memory it gives you. It only knows your program no longer needs memory after it exits.

So, ultimately free is declaring you are finished with a block of memory you got form malloc. free(a) should have been called after the second loop, because free means you are done. if you are done, you cannot truly guarantee what value will be in that memory anymore. malloc may have returned that value somewhere else for re-use, since you said you were done. In a program of this scope, it might seem like a non-issue, but this is the sort of non-issue that can easily slip in and break any reasonably complex program. A lot of people got mad at MS after moving from DOS to Windows when Sim City had a similar bug. DOS didn't enforce memory bounds, so any program could write over any other program's memory. Windows did enforce them, and Sim City [correctly] broke when it accessed some memory after freeing it.

1 Like