调试时 NOT 运行 时的分段

Segmentation when NOT running on debug

如标​​题所述,我遇到一个问题,其中一个大项目的可执行文件在运行时出现分段错误,但编译正常且未调试。

我们正在 linux SUSE 服务器上工作,代码主要是 C++。通过gdb中的bt,我已经能够看到问题到底发生在哪里,这让我想到了这个问题。该文件是自动生成的,多年未更改。现在不同的是,我们更新了第三方组件 gSOAP。在更新第三方版本之前,它在调试和非调试上都能正常工作。

有了调试标志,问题就神奇地消失了(对于像我这样的新手)。 很抱歉,它不可能包含很多代码,只有以下行:

/*------------------------------------------------------------.
| yynewstate -- Push a new state, which is found in yystate.  |
`------------------------------------------------------------*/
 yynewstate:
  /* In all cases, when you get here, the value and location stacks
     have just been pushed.  So pushing a state here evens the stacks.  */
  yyssp++;

 yysetstate:
  *yyssp = yystate; <------------------ THIS LINE

因此,我们将不胜感激。我其实不明白为什么会出现这个问题,我应该采取什么步骤来解决它。

编辑,我不希望你为我解决这个特殊情况,因为更多的是为了帮助我理解为什么在编程中会发生这种情况,我在这段代码中的情况只是一个例子。

首先,请意识到您使用的是 C++,而不是 Java 或任何其他语言,在这些语言中,您的程序的 运行 总是可以预测的,甚至 运行 时间问题也是如此可预见的。

在 C++ 中,事情不像那些语言那样是可预测的。仅仅因为您的原始程序多年未更改并不意味着该程序没有错误。这就是 C++ 的工作原理——您认为您的程序没有错误,但实际上它并不是没有错误。

从你的代码来看,异常是因为 yyssp 指向了它不应该指向的东西,并且取消引用这个指针会导致异常。这是唯一可以从您发布的代码中得出的结论。为什么指针指向它所在的位置?我们不知道,那是你需要通过调试发现的。

至于为什么 运行 在调试和发布时会有所不同——同样,像这样的错误允许程序以不可预测的方式 运行。添加或删除代码,运行 它在另一台机器上,运行 它具有不同的编译器选项,甚至可能 运行 下周它,并且它的行为可能会有所不同。

有一件事你不应该做——如果你做了一个完全不相关的代码更改并且你的程序神奇地工作了,不要声称问题已经解决或解决了。不——问题 修复——你要么掩盖了它,要么 bug 被移动到代码的另一部分,对你隐藏了。 必须 说明 为什么 修复会解决问题。

很多时候,一个天真的程序员认为四处移动东西,添加或删除行,然后宾果游戏,一切都有效,这成为了解决办法。不要落入那个陷阱。

我的团队中有人为此找到了临时解决方案, 这是构建这个库的优化标志。
我们构建的默认值是 -O2,而在调试时会发生这种变化。

使用 -O0 构建库(更改 makefile)提供了一个临时解决方案。