我相信我在 Visual Studio 2012 Update 3 C++ 编译器中发现了一个有点晦涩但可怕的错误。我在使用 gtest 编写单元测试时发现了它。测试开始显示内存泄漏,在调查问题后似乎减少到编译器中的错误。
我将问题提交给 Microsoft: https ://connect.microsoft.com/VisualStudio/feedback/details/794722/parameter-dtor-not-call-when-overloaded-operator-involved-in-return
在过去,我错误地将自己的错误称为“编译器错误”,这比我愿意承认的要多。所以我想我会在这里发布这个问题,以防有人想自己重现这个问题。如果我可以在这段代码中指出我自己的错误,那将非常有帮助!我真的希望 VC++ 编译器不会在下面的程序中调用析构函数。
请注意,错误行为是在禁用优化器时发生的,因此它不是优化器错误。
我在 gcc 4.2.1 (i686-apple-darwin11) 中尝试了这段代码,它的行为符合预期。
这是项目中单个源文件的代码:
#include <string>
int instance_count= 0;
class c {
public:
c( std::string s ) : m_s(s) { ++instance_count; }
c( const c& other ) : m_s(other.m_s) { ++instance_count; }
~c() {--instance_count;}
private:
std::string m_s;
};
class d {
public:
d() {}
void operator=(int) {}
};
void f( c c_ ) {
try {}
catch(...) { return d() = 5; }
}
int main( int argc, char* argv[] ) {
c instance("leak");
f(instance);
return instance_count == 1 ? 0 : -1;
}
要在 Visual Studio 2012 Update 3 中编译它:
- File -> New -> Project...,选择 Win32 Console Application,点击 OK 然后点击 Finish
- Build -> Configuration Manager -> Active Solution Platform -> New...,选择x64,点击OK
- 用上面的代码替换主 .cpp 文件的内容
- 将 #include "stdafx.h" 添加到文件顶部或关闭预编译器头文件
- 运行程序,注意退出代码是 -1,我希望它是 0。这似乎在 32 位和 64 位版本中重现,尽管我专注于 64 位。
- 注释掉 f() 中的 try/catch 块,注意退出代码变为 0。我不明白为什么这个更改会影响退出代码,因为 catch() 块甚至没有执行。