【问题标题】:How do I find a stack overflow problem in linux?如何在 linux 中找到堆栈溢出问题?
【发布时间】:2010-02-10 20:35:29
【问题描述】:

我正在使用第三方库编译我的应用程序,似乎有一些奇怪的行为表明存在堆栈溢出问题(这只是猜测)。

但是当我在崩溃的行之后添加一个打印语句时,应用程序运行良好。如果我删除打印语句(一个简单的 cout 上崩溃

0x00007f48f2027276 in free () from /lib64/libc.so.6

我尝试添加以下 char 数组来代替 print 语句,这也停止了崩溃,然后我尝试打印 char 数组的内容:

char ben[8000] = {0};
memset(&ben, 0, sizeof (ben));

for (int y = 0; y < 8000; ++y)
{
if (ben[y] != 0)
  PRINT ("CHAR[%d]=%d", y, ben[y]);
}

查看数组中是否有任何内容损坏,但这种方法不起作用。所以我想知道是否有更好的方法来检测这是否是堆栈溢出问题?

我使用 -fstack-protector-all(lib 和我的代码)重新编译了应用程序,但没有出现任何问题。我还尝试了 valgrind,它没有给我任何看起来可疑的东西。

它似乎崩溃了,因为我试图释放一个无效的指针,但我不知道为什么指针是无效的,因为它正在释放一个局部变量(即当它超出范围时)。指针被损坏是有原因的,但这有点像大海捞针。有没有什么好的技术可以尝试解决这类问题?非常感谢!

【问题讨论】:

  • 您看到的是堆损坏的典型症状。错误几乎肯定不在发生崩溃的代码中,甚至不在发生崩溃的代码附近。
  • Valgrind 不会发现堆损坏问题(即,如果我错误地删除了两次)那你为什么说这是一个堆问题?
  • 我想知道 StackOverflow 有多少堆栈溢出问题?
  • @John,我真的很想知道。另外:我们是否需要一个“NOT-Meta”标签来表明它不属于 meta-stackoverflow? B-)(是的,显然,实际上阅读帖子,甚至主题,都会解决这个问题......)

标签: c++ debugging overflow


【解决方案1】:

使用-fstack-protector-all 编译将使程序知道堆栈是否被破坏。

【讨论】:

  • 听起来好像不是堆栈溢出问题。
【解决方案2】:

你应该试试valgrind 的 Memcheck 工具。它是一个内存调试器,它会让你知道你是否访问了你不应该访问的内存(堆栈溢出、双重释放、访问释放的指针、数组溢出等情况)

【讨论】:

  • 我在 Valgrind 中尝试过,但简单的 --tool=memcheck 一无所获,所以我不确定 valgrind 还能提供什么?
  • 这很奇怪。我的 C/C++ 有点尘土飞扬,我认为你的 memset 是有原因的。 ben 是一个数组,因此变量已经是一个指针,所以你应该说memset(ben,0,sizeof(ben))。不过,我并不是 100% 有信心。
  • 数组不是指针,尽管它们在需要时默默地衰减为指针。然而,在这种情况下,&amp;ben == (void*) ben.
  • @Porculus:感谢您的更正。所以我对我的 C/C++ 尘土飞扬的事实是正确的 :)
【解决方案3】:

这听起来像是指针损坏问题,而不是堆栈溢出。如果应用程序很大,请尝试在主要函数的顶部插入return,以限制执行的代码量。

一旦可疑代码的范围受到限制,请仔细进行桌面检查指针管理。尤其要确保任何发送到 free() 或析构函数的指针都没有事先被丢弃。

【讨论】:

  • 指针很可能已损坏,但有没有更好的方法来找出它可能损坏的位置?我已经尝试返回,当函数中的变量超出范围时,应用程序会免费崩溃,但我看不到指针在哪里损坏。
  • 您可能会很幸运使用工具,但没有调试器或 IDE 的干扰检查每一行代码是无可替代的。
  • 相反。有很多很棒的替代品。例如,通过 with 调试器遍历每一行。盲目地盯着一页又一页的代码会很快让你的大脑麻木。
  • 也许这就是心态。不管你怎么做,都要把每一行代码都当作嫌疑犯——直到被证明是无辜的。
【解决方案4】:

如果 memcheck/valgrind 没有打开任何东西,您可以随时启动 gdb 并查看程序集。

要检查的其他一些内容是未初始化的变量,已知这些会导致意外错误。如果你还没有使用 -Wall,也可以使用它,它可能会出现问题。

这听起来确实像一个糟糕的指针问题。请参阅 this site 了解一些好的提示。

【讨论】:

    【解决方案5】:

    这是一条非常可疑的线,我认为应该是这样的

    memset(&ben, 0, sizeof(ben) - 1);

    你得到了memset 来遍历数组....

    希望这会有所帮助, 此致, 汤姆。

    【讨论】:

    • 真的-为什么-1?。 sizeof(ben) = 8000, ben 有 8000 个槽
    • @pm100: memset 看起来确实越过了数组并越过了边界... :)
    • @tommieb75 : memset 可以安全地用零写入本的完整大小。
    • 行没有错,但完全没必要,因为={0}已经保证内存会被零填充。
    • @Tommieb75:只要您使用的是 C 编译器,就不会。 (顺便说一句,之前的评论应该是“设置为 0(如 '\0',NUL 字符)而不是 '0'”,我搞砸了格式)
    猜你喜欢
    • 2010-10-15
    • 2017-09-29
    • 1970-01-01
    • 2014-04-15
    • 2017-05-02
    • 2019-05-18
    • 2012-09-18
    • 2017-07-02
    相关资源
    最近更新 更多