为什么抛出stringstream :: str()导致Windows应用程序崩溃?

时间:2017-10-27 15:37:56

标签: c++ windows mingw throw

我有一些Linux代码我试图在Windows中重复使用。我使用编译器并使用Qt 5.9.1进行安装,并且我使用googletest进行单元测试。在Linux下正常测试的是在Windows下中止。 (参见What is the cause of "This application has requested the Runtime to terminate it in an unusual way"?我知道它是如何中止的。)

工具版本信息:

  • googletest
    • Git label" release-1.8.0"
  • cmake的
    • 3.9.1
  • 的i686-W64-的mingw32-G ++
    • (i686-posix-dwarf-rev0,由MinGW-W64项目建造)5.3.0
  • 的mingw32-MAK​​E
    • GNU Make 4.1,专为i686-w64-mingw32而建。

将生成错误的简化代码:

- MyClass.h

#pragma once

class MyClass
{
public:
  MyClass();
  ~MyClass();

  void Func();
};

- MyClass.cpp

/*01*/   #include "MyClass.h"
/*02*/  
/*03*/   #include <sstream>
/*04*/   #include <stdexcept>
/*05*/  
/*06*/   namespace {
/*07*/    std::stringstream ss;
/*08*/  }
/*09*/  
/*10*/  MyClass::MyClass() {}
/*11*/  MyClass::~MyClass() {}
/*12*/   
/*13*/  void MyClass::Func() {
/*14*/    std::stringstream ss;
/*15*/    ss << "BOO!";
/*16*/    throw std::runtime_error( ss.str() );
/*17*/    //throw std::runtime_error( std::string( ss.str().c_str() ) ); 
/*18*/    //throw std::runtime_error( "BOO!" );                          
/*19*/  }

- MyClassTestSuite.cpp

#include <gtest/gtest.h>

#include <MyClass.h>
#include <stdexcept>
#include <iostream>

class MyClassTestSuite: public ::testing::Test
{
};

TEST_F( MyClassTestSuite, test_FuncThrows )
{
  MyClass obj;

  try
  {
    obj.Func();
    FAIL();
  }
  catch( std::runtime_error & e ) {}
}

我得到的错误是:

This application has requested the Runtime to terminate it in an unusual way.

关于MyClass.cpp中注释掉的代码:

  • 用第17行替换第16行仍会产生错误。
  • 用第18行替换第14-17行不会产生错误。
  • 注释第14行以允许匿名命名空间ss成为用于创建异常的范围内变量不会产生错误。

---更新------

当我创建一个main并在使用cmake的范围之外运行它时:

main.cpp中:

#include "MyClass.h"
#include <stdexcept>
#include <iostream>

int main( int, char** )
{
  MyClass obj;

  std::cout << "Calling\n";
  try
  {
    obj.Func();
    std::cout << "Call successful\n";
  }
  catch( const std::runtime_error & e )
  {
    std::cout << "Caught exception " << e.what() << "\n";
  }

  return 0;
}

输出:

C:\> i686-w64-mingw32-g++.exe MyClass.cpp main.cpp -o test.exe
C:\> test.exe
Calling
Caught exception BOO!

因此异常被正确抛出并被捕获。

我已经运行了ldd,而ldd给出的答案是,无效的独立主程序和无法运行的单元测试程序都具有完全相同的依赖关系链。

This post表明可能会有一些微软重写的东西是罪魁祸首。 (掌握很多吸管之一。)

- 奇怪------

  • 在同一个项目中是一个模块,它完成同样的事情但没有问题。主要区别在于该模块的功能有用,然后决定是否抛出;与MyClass::Func()只会抛出。
  • 我的简化代码来自基类。如果我使ss成为基类的受保护成员,则派生类按预期运行(无错误)从基类抛出会导致中止。
  • 我移植了另一个图书馆(因为这是最初发布的),对于该库,有一个googletest测试套件在我禁用-O3优化开关之前无法正常工作。我已尝试使用此库但它没有效果。

这开始感觉像是编译器中的一个错误,但我怎么能证明这一点? (我的期望是,在试图证明它时,我找到了根本原因并且它不会成为编译器。编译器不会被扔进野外&#34; willy-nilly。)这个错误真的感觉就像变量在内存释放后被引用一样。

- 可能是罪魁祸首------

在阅读differences between SJLJ, SEH, and DW2后,我了解到有不同的异常类型(谁知道?不是我,直到5分钟前)和SEH是Windows喜欢的,特别是在64位计算机上。我怀疑这是我的问题,尽管我还没有证明这一点。我的工具链开发过程让我走上了一条道路,现在这应该是一个非问题,但这是我的帽子,所以下次我遇到这个问题我会知道在哪里检查。知道是战斗的一半......

0 个答案:

没有答案