这是C语言类(class)中的一个问题。有人想从带有指针的函数返回一个值。他将指针地址分配给 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;
}
最佳答案
当函数被调用时,参数(以相反的顺序)、返回地址和调用者的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
我很高兴看到这个问题的更清晰或不同的解释。
关于c - 函数调用后返回的指针值意外更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25789895/