这是C语言课程的问题。有人想从带有指针的函数返回一个值。他将指针地址分配给result_ptr并打印该指针的值。
当没有A行时,printf()工作正常:printf()打印3.
但是,当在printf()前面调用另一个addition()函数时,会发生错误:printf()打印5。
如果线A被注释掉,线B,另一个printf()函数被取消注释:printf()打印0。
到底发生了什么?
int *addition(int a, int b) {
int d = a + b;
int *c = &d;
return c;
}
int main(int argc, const char * argv[])
{
int *result_ptr = addition(1, 2);
addition(2, 3); // Line A
// printf("Another line\n"); // Line B
printf("result = %d \n", *result_ptr);
return 0;
}
答案 0 :(得分:2)
当调用函数时,参数(以相反的顺序),返回地址和调用者的EBP(存储函数在执行后返回的位置)被压入堆栈。被调用者设置一个堆栈帧,存储其局部变量并保存3个寄存器的内容,如果它们被修改,则保存EBX,ESI和EDI。当函数完成执行时,框架会弹出,堆栈的顶部返回到调用被调用者之前的高度。
在此示例中,int * c声明一个本地指针变量,该变量存储在被调用者帧内的堆栈中。返回该指针返回堆栈帧上的地址。由于连续的addition()调用会导致相同的堆栈空间分配,因此相同地址的内容将被写入两次。这就是为什么第二个函数调用将写入5,从第一个函数调用覆盖3:它们正在修改同一内存位置的值。但是,当调用printf()时,堆栈空间用于完全不同的堆栈帧。然后,同一位置存储未定义的值。
为了避免这种情况,最好将指针返回到堆上的位置而不是堆栈上。注意在内存分配后释放指针以避免泄漏。
int *addition(int a, int b) {
int *c = (int *) malloc(sizeof(int));
*c = a + b;
return c;
}
// in main
int *result_ptr=addition(1,2);
printf("value = %d \n",result_ptr);
free(result_ptr);
result_ptr=0;
参考:http://www.csee.umbc.edu/~chang/cs313.s02/stack.shtml
我很高兴看到这个问题有更明确或不同的解释。