如何调试异常 C 内存/堆栈问题

发布于 2024-09-01 23:11:48 字数 934 浏览 6 评论 0 原文

抱歉,我无法具体说明代码,但我看到的问题是异常的。字符串值似乎会根据其他不相关的代码而发生变化。例如,下面传递的参数值将仅根据我是否注释掉一两个 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);
}

周围有更多的代码,所以我不能要求别人调试我的程序——我想知道的是我如何调试为什么这样的字符串根据不相关的代码更改或覆盖他们的内存。我的记忆力有限吗?我的堆栈太小?我怎么知道?我还能做什么来追踪问题?我的程序并不大,就像一千行代码和几个动态链接的外部库,但没有什么特别的。

帮助!蒂亚!

Sorry I can't be specific with code, but the problems I am seeing are anomalous. Character string values seem to be getting changed depending on other, unrelated code. For example, the value of the argument that is passed around below will change merely depending on if I comment out one or two of the fprintf() calls! By the last fprintf() the value is typically completely empty (and no, I have checked to make sure I am not modifying the argument directly... all I have to do is comment out a fprintf() or add another fprintf() and the value of the string will change at certain points!):

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);
}

There's more code all around, so I can't ask for someone to debug my program -- what I want to know is HOW can I debug why character strings like this are getting their memory changed or overwritten based on unrelated code. Is my memory limited? My stack too small? How do I tell? What else can I do to track down the issue? My program isn't huge, it's like a thousand lines of code give or take and a couple dynamically linked external libs, but nothing out of the ordinary.

HELP! TIA!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

写给空气的情书 2024-09-08 23:11:48

简单:

  1. 学习使用Valgrind,特别是memcheck
  2. 学习使用GDB 包括断点和变量检查
  3. 熟能生巧。

那应该排序它。确保在 GCC 上使用 -g 选项编译任何库,这会保留调试符号,以便您的调试输出更有意义。

Simple:

  1. Learn to use Valgrind, specifically memcheck
  2. Learn to use GDB including break points and variable inspection
  3. Practice makes perfect.

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.

弥繁 2024-09-08 23:11:48

有两种情况需要考虑:

  1. arg 变量在 process_args 的开始和结束之间更改值。
  2. 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 提供任何进一步的建议,因为您还没有透露您的实际平台是什么。

There are two cases to consider:

  1. The arg variable changes value between the start and finish of process_args.
  2. The arg stays the same, but the string it points to is changed.

Your description and your code doesn't differentiate between the two, but it's important to know which of the two is actually happening.

This will reveal the answer:

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);

Most often arg is not changing (i.e. you have case 2). If so, something is corrupting the string you've allocated. Valgrind, suggested already, but available only on Linux, AIX and MacOSX, has only a 50:50 chance of finding the problem. What you really want is a GDB watchpoint: set breakpoint at the start of process_args, once hit, do (gdb) watch *(long*)arg and continue. GDB will stop when something writes to *arg (it will actually stop on the next instruction). Then use (gdb) where command to figure out what's happening.

If you actually have arg changing its value (case 1), that may be harder to debug, and indicates stack corruption of some sort, or a violation of procedure calling conventions for your platform. Valgrind will likely not help at all with that. This is more consistent with the behavior you described: commenting out unrelated code causes the bug to shift.

I can't give any further advice on debugging case 1 though, since you haven't revealed what your actual platform is.

GRAY°灰色天空 2024-09-08 23:11:48

如果您正在编写用户级应用程序,Valgrind 是检测内存问题(例如内存泄漏、缓冲区溢出等)的不错选择。以下是快速入门指南:http://valgrind.org/docs/manual/QuickStart.html

If you are writing user-level applications, Valgrind is a good choice to detect memory problems such as memory leaks, buffer overflow, etc. Here is a quick start guide: http://valgrind.org/docs/manual/QuickStart.html

岁月流歌 2024-09-08 23:11:48

您没有提供开发工具,但如果您像 90% 的程序员一样,您已经在使用带有调试器的 IDE 来处理此问题,则不需要新工具。对保存字符串的内存块设置监视,然后单步执行代码并查看字符串何时发生更改。

You don't give your dev tools, but if you're like 90% of coders you're already using an IDE with a debugger which can handle this, no new tools required. Set a watch on the chunk of memory holding your strings, then step through your code and see when the strings get changed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文