函数调用跳转到错误的函数

15

我正在使用VS2008编译一个C++静态库,在解决方案中也有一个启动项目,它使用该库,而且运行良好。

但是,在另一个解决方案中使用该库时,出现了运行时检查失败的问题。 “ESP的值在函数调用跨度过程中没有得到正确保存。” 通过代码逐步执行,我发现函数foo()在崩溃之前会跳转到bar()。所涉及的函数只是常规函数,没有函数指针。

有人知道可能发生了什么问题,以及为什么在使用相同解决方案下的库时会正常工作吗?

编辑:这些函数(方法)是类的一部分,如果这有助于解决问题。


这些函数实际上是方法吗? - user3458
是的.. 可能应该提到它们是类的一部分。您有可能造成这种情况的想法吗? - Archon
这只是我在XCode中遇到的情况,答案已经澄清了为什么会发生这种情况。对我来说,它调用了一个完全不同的头文件的功能,所以我删除了“virtual”,现在它可以工作了,但重新编译可能是修复它的原因。奇怪的错误。 - Stephen J
5个回答

16

请原谅我在这里阐述显而易见的事情,但是......当对象(.o)和头文件(.h)不同步时,我已经看到过很多次出现这种情况。特别是涉及虚拟方法时。

考虑以下情况:对象文件是使用头文件编译的:

class Foo { virtual void f(); };

但是然后头部被更改为:

class Foo { virtual void g(); virtual void f(); };

对于下一个目标文件,编译器对类的vtable中f()所在位置的假设是不正确的。

通常情况下,重新编译所有内容会有所帮助。


这似乎是情况,出现错误的解决方案正在使用过时的头文件,感谢您的帮助。 :) - Archon
@Mr.Ree,我遇到了同样的问题,原因也是一样的,但是我不明白为什么会发生这种情况。如果我们已经更新了静态库(头文件可能较旧),静态库应该具有正确的函数地址,那么链接器不应该得到正确的函数吗? - Abhi9
在我的情况下,重建没有帮助。我现在该怎么办? - Adrian
好的 - 我已经通过这个答案解决了这个问题:https://dev59.com/HFLTa4cB1Zd3GeqPdtCg#38350051 简短的故事:头文件和实际实现文件之间的#define不一致。 - Adrian

7

这很可能是由于不兼容的调用约定引起的,即库和调用者对堆栈布局有不同的想法。

请查看MSDN获取更多信息。


在解决方案属性中,两个解决方案都使用__cdecl (/Gd),因此它们之间没有区别。 - Archon
嗯...调用前后的汇编代码是什么样子? - Arnout

3
  • 请确保你在项目中选择的不是旧版本的库,例如(如Adam所提到的),你选择了一个较旧的调试版本而不是当前发布版本或反之亦然。

  • 您可能需要重新构建。

  • 还要注意条件编译,其中宏可能会在某个时刻被#定义或#undef'd(另一种解决方案可能具有某些宏或预定义)。有时删除.lib .obj和预编译头缓存并进行重建可能会有所帮助。

  • 有可能是IDE或项目配置出了问题,您可能需要从头开始重新创建项目。

  • 我对MS VC不是很熟悉,您能否添加另一个解决方案中的库项目文件?例如,在Borland C++ Builder中,您可以定义项目组并构建/制作多个项目,我总是将我使用的库的项目放在我的程序项目组中,这样在构建时所有内容都会得到更新。


2

请确保您在调试时编译的是Debug模式而不是Release模式。如果您尝试在Release模式下调试程序,由于优化的原因,从调试器中获取的数据将会是垃圾。


在 Debug 和 Release 模式下编译两个解决方案。但是在 Debug 模式下进行了步进,因此不应该有任何垃圾。 - Archon

1

我记得在二进制文件的结构成员对齐(/Zp编译器开关)不同时会出现这样的情况。你也可以检查一下。

通过#pragma pack设置而不是通过项目设置设置应该更安全。


两个解决方案都将其设置为默认值。 - Archon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接