• We’re currently investigating an issue related to the forum theme and styling that is impacting page layout and visual formatting. The problem has been identified, and we are actively working on a resolution. There is no impact to user data or functionality, this is strictly a front-end display issue. We’ll post an update once the fix has been deployed. Thanks for your patience while we get this sorted.

C question and memory

AgentEL

Golden Member
I know this is bad:

int * f1(){
int j;

j=100;

return &j;
}

When f1 returns, the memory taken by j may or may not be reclaimed, which is bad.

But is this bad?

void f2(){
int j;

f3(&j);

return;
}

void f3(int * ptr){
printf("%d\n", *ptr);
}

I would say the contents of j will still be preserved since f2 hasn't yet returned. Can anyone confirm this, please? Thanks!
 
I'm not sure but if you do something like this:

int *foo = f1();

Then free 'foo' accordingly then you should be OK.

This is just a guess though. I'm still a bit vague about memory allocation myself.
 
At first glance that should work fine because when f3 is called j will still be in scope so you can pass it's value or data round.

I'm not sure but if you do something like this:

int *foo = f1();

Then free 'foo' accordingly then you should be OK.

This is just a guess though. I'm still a bit vague about memory allocation myself.

You missed the point. The problem with his first situation is that he returns &j which is the memory address at which j is kept, but after f1() returns j will be out of scope and won't exist so the memory address will be invalid. Worst case the program will crash from a segfault and best case the program will continue but with random data being at &j which will most likely corrupt the results of whatever the rest of the program is doing.
 
Originally posted by: Nothinman
At first glance that should work fine because when f3 is called j will still be in scope so you can pass it's value or data round.

I'm not sure but if you do something like this:

int *foo = f1();

Then free 'foo' accordingly then you should be OK.

This is just a guess though. I'm still a bit vague about memory allocation myself.

You missed the point. The problem with his first situation is that he returns &j which is the memory address at which j is kept, but after f1() returns j will be out of scope and won't exist so the memory address will be invalid. Worst case the program will crash from a segfault and best case the program will continue but with random data being at &j which will most likely corrupt the results of whatever the rest of the program is doing.

I thought the value would be kept after the function returns, but I see what you're saying about &j going out of scope. How about passing &j as a parameter? Would that work?
 
I thought the value would be kept after the function returns, but I see what you're saying about &j going out of scope. How about passing &j as a parameter? Would that work?

That would require allocationg j outside of the f1 call and passing it's address into f1 which changes the API of f1, but yes it would still be in scope after f1 returns control back to the calling function.
 

Your first example is returning the address of something that is on the stack and goes out of scope immediately after you return, leading to the results that Nothinman described. The second example looks fine to me, although obviously for an int, a pointer is silly (I'm assuming it is a simplification of your real code).
 
As a general rule of thumb, passing the address of stack-allocated ("local") variables as a parameter to a function is OK as long as the function doesn't store the address for later use elsewhere (i.e., after the function returns). That can create a construct known as a "dangling reference", which is what Nothinman was talking about. The memory address would point to an invalid memory location:

int * g_pTheResult; // global pointer to the result of the calculation

int main() {
Calculate();
if ( NULL != g_pTheResult ) {
printf("The result is %d", *pTheResult); // may crash here!
}
return 0;
}

void Calculate() {
int i;
i = 1 + 2 + 3;
g_pTheResult = &i; // error! g_pTheResult is dangling as soon as Calculate() exits
}

The scary part is that the above code might actually RUN and produce the correct output. It's due to the fact that the discarded stack frame from Calculate() is still "sitting around" and simply hasn't been overwritten. So when printf() reads from the address located on this defunct stack frame, the old result (6) will still be there. And while the address is technically invalid, the OS won't be able to detect the invalid memory access because it can only detect invalid Page accesses. Because x86 architectures use 4kb pages and the above functions have stack frames that are only a few bytes long, there is a high probability that both stack frames are on the same (valid) page and the OS would not catch the violation.

Note that the problem with the code above has nothing to do with "reclaiming memory". Reclaiming memory is only an issue when you're dealing with heap-allocated ("dynamic") variables. The compiler ensures all local variables are "reclaimed" appropriately. The programmer gets this for free.
 
Originally posted by: BingBongWongFooey
Your first example is returning the address of something that is on the stack and goes out of scope immediately after you return, leading to the results that Nothinman described. The second example looks fine to me, although obviously for an int, a pointer is silly (I'm assuming it is a simplification of your real code).

Ditto.

Automatic variables are deallocated when the closing } is reached, and never before. Many many system calls on all kinds of platforms take pointers or are call-by-reference. If the data local to your function is passed to another function (even through a pointer) it better still exist!
 
Back
Top