如何调试异常 C 内存/堆栈问题
抱歉,我无法具体说明代码,但我看到的问题是异常的。字符串值似乎会根据其他不相关的代码而发生变化。例如,下面传递的参数值将仅根据我是否注释掉一两个 fprintf() 调用而改变!到最后一个 fprintf() 时,该值通常完全为空(不,我已经检查过以确保我没有直接修改参数...我所要做的就是注释掉 fprintf() 或添加另一个 fprintf()并且字符串的值会在某些点发生变化!):
static process_args(char *arg) {
/* debug */
fprintf(stderr, "Function arg is %s\n", arg);
...do a bunch of stuff including call another function that uses alloc()...
/* debug */
fprintf(stderr, "Function arg is now %s\n", arg);
}
int main(int argc, char *argv[]) {
char *my_arg;
... do a bunch of stuff ...
/* just to show you it's nothing to do with the argv array */
my_string = strdup(argv[1]);
/* debug */
fprintf(stderr, "Argument 1 is %s\n", my_string);
process_args(my_string);
}
周围有更多的代码,所以我不能要求别人调试我的程序——我想知道的是我如何调试为什么这样的字符串根据不相关的代码更改或覆盖他们的内存。我的记忆力有限吗?我的堆栈太小?我怎么知道?我还能做什么来追踪问题?我的程序并不大,就像一千行代码和几个动态链接的外部库,但没有什么特别的。
帮助!蒂亚!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

发布评论
评论(4)
有两种情况需要考虑:
arg
变量在process_args
的开始和结束之间更改值。arg
保持不变,但它指向的字符串发生了变化。
您的描述和代码并不能区分两者,但了解两者中的哪一个实际发生很重要。
这将揭示答案:
fprintf(stderr, "Function arg is %s (%p)\n", arg, (void *)arg);
... do bunch of stuff ...
fprintf(stderr, "Function arg is now %s (%p)\n", arg, (void *)arg);
大多数情况下 arg
不会改变(即情况 2)。如果是这样,则某些东西正在破坏您分配的字符串。 Valgrind 已被建议,但仅在 Linux、AIX 和 MacOSX 上可用,只有 50:50 的机会发现问题。您真正想要的是一个GDB观察点:在process_args
开始处设置断点,一旦命中,执行(gdb) watch *(long*)arg 和<代码>继续。当有东西写入
*arg
时,GDB 将停止(它实际上会在下一条指令处停止)。然后使用 (gdb) where
命令来弄清楚发生了什么。
如果您确实让 arg
更改了其值(情况 1),则可能更难调试,并且表明某种堆栈损坏,或者违反了您平台的过程调用约定。 Valgrind 可能对此毫无帮助。这与您描述的行为更加一致:注释掉不相关的代码会导致错误转移。
不过,我无法就调试案例 1 提供任何进一步的建议,因为您还没有透露您的实际平台是什么。
如果您正在编写用户级应用程序,Valgrind 是检测内存问题(例如内存泄漏、缓冲区溢出等)的不错选择。以下是快速入门指南:http://valgrind.org/docs/manual/QuickStart.html
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
简单:
那应该排序它。确保在 GCC 上使用
-g
选项编译任何库,这会保留调试符号,以便您的调试输出更有意义。Simple:
That should sort it. Make sure you compile any libraries with the
-g
option on GCC, which keeps debugging symbols so your debugging output makes more sense.