无法追踪潜在的内存覆盖。 Windows奇怪

这使我疯狂。 我正在使用Windows .lib中的一些第三方代码,在debugging模式下,导致类似于以下内容的错误:

Run-Time Check Failure #2 - Stack around the variable 'foo' was corrupted. 

当对象超出范围或被删除时引发错误。 简单地分配这些对象之一,然后删除它将引发错误。 因此,我认为问题是在许多构造函数/析构函数中的一个中,但是尽pipe遍历每行代码,我找不到问题。

但是,只有在静态库中创build这些对象时才会发生这种情况。 如果我在我的EXE应用程序中创build一个,错误不会出现。 第三方代码本身存在于一个静态库中。 例如,这失败了:

 **3RDPARTY.LIB** class Foo : public Base { ... }; **MY.LIB** void Test() { Foo* foo = new Foo; delete foo; // CRASH! } **MY.EXE** void Func() { Test(); } 

但是这将工作:

 **3RDPARTY.LIB** class Foo : public Base { ... }; **MY.EXE** void Func() { Foo* foo = new Foo; delete foo; // NO ERROR } 

因此,删除“中间”.lib文件会使问题消失,正是这种令人生厌的情绪正在使我发疯。 EXE和2个库都使用相同的CRT库。 没有错误链接。 第三方代码使用inheritance,并有5个基类。 我尽可能多地评论了代码,同时仍然可以构build代码,而我只是看不到有什么问题。

所以如果有人知道为什么.lib中的代码对.exe中的相同代码采取不同的行为,我很乐意听到它。 同上任何提示追查记忆覆盖! 我正在使用Visual Studio 2008。

一种可能性是调用约定不匹配 – 确保你的库和可执行文件都被设置为使用相同的默认调用约定(通常是__cdecl)。 要设置它,请打开项目属性并转至配置属性> C / C ++>高级,然后查看“ 调用约定”选项。 如果你用错误的调用约定来调用一个函数,你会完全搞砸堆栈。

好,我跟踪了这​​个问题,如果有人感兴趣的话,这个问题就是一个黑客。 基本上,我的.LIB,展示了这个问题。 已将_WIN32_WINNT定义为0x0501 (Windows 2000及更高版本),但是我的EXE和第三方LIB将其定义为0x0600 (Vista)。 现在,第三方库包含的头文件之一是sspi.h ,它定义了一个名为SecurityFunctionTable的结构,它包含以下片段:

 #if OSVER(NTDDI_VERSION) > NTDDI_WIN2K // Fields below this are available in OSes after w2k SET_CONTEXT_ATTRIBUTES_FN_W SetContextAttributesW; #endif // greater thean 2K 

简而言之,这意味着LIB之间的对象大小不匹配,导致运行时检查失败。

类!

.lib文件是否与库的.lib链接? 我从你的例子中假设你正在包含头文件和析构函数的声明; 没有它,删除这种类型是允许的,但可能导致UB(以一种奇怪的方式违背一般规则,即在使用之前必须定义的东西)。 如果.lib文件没有链接在一起,那么自定义operator delete或析构函数有可能存在一些奇怪的链接问题,而这种情况不应该发生,否则你永远无法确定它是否会发生。

没有看到更多的代码,很难给你一个坚定的答案。 但是,为了追踪内存覆盖,我建议使用WinDbg(免费从Microsoft搜索“ Windows调试工具 ”)。

当你把它连接到你的进程时,你可以设置内存访问的断点(读,写,或执行)。 总体来说它确实很强大,但是它应该特别帮助你。

当对象超出范围或被删除时引发错误。

每当我遇到这个问题时,就必须使用与应用程序的其余部分不同的C ++运行时版本来编译库。