无法跟踪潜在的内存覆盖。 Windows怪异

时间:2008-12-12 16:44:03

标签: c++ windows

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

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

当对象超出范围或被删除时,抛出错误。只需分配其中一个对象然后删除它就会抛出错误。因此,我认为问题出在许多构造函数/析构函数中的一个,但是尽管逐步执行每行代码,我都找不到问题。

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

**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库。链接没有错误。第三方代码使用继承,有5个基类。我已尽可能多地注释掉代码,同时仍然需要构建代码,而我却看不到它是什么。

因此,如果有人知道为什么.lib中的代码会对.exe中的相同代码采取不同的行为,我很乐意听到它。跟踪记录覆盖的任何提示都是一样的!我正在使用Visual Studio 2008。

5 个答案:

答案 0 :(得分:2)

一种可能性是calling convention不匹配 - 确保您的库和可执行文件都设置为使用相同的默认调用约定(通常为__cdecl)。要进行设置,请打开项目属性并转到配置属性> C / C ++>高级并查看呼叫约定选项。如果使用错误的调用约定调用函数,则会完全搞乱堆栈。

答案 1 :(得分:2)

好的,我跟踪问题,如果有人感兴趣的话,这是一个破解者。基本上,我的.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之间的对象大小不匹配,这导致运行时检查失败。

类!

答案 2 :(得分:0)

你的.lib文件是否链接到库的.lib?我假设您的示例中包含了带有析构函数声明的标题;没有它,允许删除这种类型,但可能导致UB(以一种奇怪的方式违背一般规则,即在使用之前必须定义某些内容)。如果.lib文件没有链接在一起,那么自定义operator delete或析构函数可能会出现一些奇怪的链接问题,虽然这不应该发生,但你永远无法确定它是否会发生。< / p>

答案 3 :(得分:0)

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

当您将其附加到进程时,可以让它为内存访问(读取,写入或执行)设置断点。它总体上非常强大,但它应该特别有助于你。

答案 4 :(得分:0)

  

当对象超出范围或被删除时,抛出错误。

每当我遇到这种情况时,它都必须使用与应用程序其余部分不同的C ++运行时版本来编译库。