为啥这个变量在 return 语句之后会改变?

Posted

技术标签:

【中文标题】为啥这个变量在 return 语句之后会改变?【英文标题】:Why would this variable change after a return statement?为什么这个变量在 return 语句之后会改变? 【发布时间】:2011-09-04 04:57:07 【问题描述】:

我有一个带有签名的函数:

int exe(int stack[][STACKSIZE], int sp[], int reg[][REGISTERSIZE], int next_instruct[],
        int next_inst[], int cur_proc, int *terminate);

最后两行:

printf("TWO cur_proc: %d\n",cur_proc);
return NORMAL;

并且是这样调用的:

printf("ONE cur_proc: %d\n",cur_proc);
msg = exe(stack,sp,reg, next_instruct, next_instruct, cur_proc, &terminate);
printf("THREE cur_proc: %d\n",cur_proc);

我正在传入cur_proc,它被认为是exe() 内部的“只读”(不是按值传递的)变量。在exe() 内做我的事情。

我的输出是:

ONE cur_proc: 1
TWO cur_proc: 1
THREE cur_proc: -1

这让我很困惑,因为我看不出有任何理由可以用否定的方法覆盖它。

这种奇怪行为的可能原因是什么?

【问题讨论】:

查看 cur_proc 何时更改其值的一种简单方法是在参数声明前加上 const。编译器将在您更改其值的确切位置引发错误。 我先试过了。没有错误,因为据编译器理解,它没有改变。 然后使用valgrind 运行您的程序。您程序的另一部分可能正在破坏您的堆。 确实如此。常数设置得太小。 【参考方案1】:

您可能在其中一个数组的范围之外写入。

在函数内部,您正在查看调用函数中变量的副本,而不是原始变量。因此,函数内的printf() 不会告诉您值何时在调用函数中损坏。

查看传递的数组,函数内部被修改的数组最有可能是罪魁祸首——或者被修改的数组。由于没有一个数组是 const 限定的,因此很难说哪些被修改了,但有些东西可能超出了界限。

如果您想跟踪调用函数中对 cur_proc 的更改何时从被调用函数内部发生,请将指向 cur_proc 的指针传递给函数 - 以及或代替值 - 并打印值通过指针。

【讨论】:

就是这样。堆栈函数在其范围之外写入。查看指向 cur_proc 的指针清除了它。【参考方案2】:

如果您的 exe 函数中的代码将数据写入传入的数组之一中的无效位置,则堆栈可能会损坏,这可能会更改堆栈更高的局部变量的值(以及其他错误东西)。

从函数的角度来看,鉴于您的变量的只读性质,无论是这种情况正在发生,还是另一个线程正在修改 cur_proc 的值 - 如果您不摆弄线程,前者似乎更有可能。

大多数调试器允许您在“更改内存中特定地址的值”上放置断点。如果你得到了 cur_proc 的地址并在这个地址的值发生变化时中断了你应该找到你的罪魁祸首。

【讨论】:

这也是我的第一个想法,但我以前从未见过。我将如何调试它? (顺便说一句,它是非线程的) 大多数调试器允许您在“更改内存中特定地址的值”上放置断点。如果你得到了 cur_proc 的地址并在这个地址的值发生变化时中断,你应该找到你的罪魁祸首。 ...话虽如此,Jonathan Leffler 在他的回复中描述了一种技术含量较低且更简单的方法,如果您不了解调试器的方式 - 非常值得考虑。 顺便说一句,您知道任何学习 gdb 或类似工具(命令行调试器)的好资源吗?

以上是关于为啥这个变量在 return 语句之后会改变?的主要内容,如果未能解决你的问题,请参考以下文章

异常处理关于return语句的执行顺序注意事项

try{}里有一个return语句,那么紧跟在这个try后的finally{}里的代码会不会被执行,什么时候被执行,在return前还是后?

try catch finally

为啥 Map 在这个例子中有一个 return 语句? [复制]

为啥 return 语句会破坏条件运算符?

如果评估的变量为 False,为啥我的 django 模板中的这个 IF 语句会执行?