Gcc5.3.0中调试和发布之间的奇怪行为

Gui*_*let 5 c++ c++11 c++14

情况

我使用Mingw在Window 7上提供的GCC 5.3.0,以及gtest来实现和运行单元测试.

在我的项目中,我有一个计算机层次结构,它实现了Computer如下界面:

class Dataset; // Not

// Interface Computer
class Computer {
public:
    // Destructor virtual to enable vmap
    virtual ~Computer() noexcept = default;

    // Pure virtual fonctions
    virtual bool preCompute(Dataset &datas) const = 0;
    virtual void compute(Dataset &datas) const = 0;


};
Run Code Online (Sandbox Code Playgroud)

我提供了这个接口的抽象实现ChainableComputer,它实现了另一个接口(Chainable)和默认实现precompute.见下文.

class ChainableComputer : public Computer, public Chainable {
    public:
         bool preCompute(Dataset &dataset) const  override;
};
Run Code Online (Sandbox Code Playgroud)

这些类位于命名空间中,称为corecore.dll,并打包在core.dll中

在另一个DLL中,我ChainableComputer在另一个命名空间中实现domain.

有些实现很简单,并且在preCompute中没有任何事情要做,因此,它们以相同的方式实现计算:

class SomeComputerImpl  : public ChainableComputer{
/// ...
void compute(Dataset &datas) const override final{
       auto result = preCompute(datas);
       if(!result){
          throw;
       }
}
};
Run Code Online (Sandbox Code Playgroud)

这段代码正在传播,所以我决定重构并在计算机中添加一个受保护的方法:

class Computer  {
/// ...
protected:
    // Helper function for some implementations of Computer
    void doPrecomputeOrThrow(Dataset &datas) const{
       auto result = preCompute(datas);
       if(!result){
          throw;
       }
    } 
}
Run Code Online (Sandbox Code Playgroud)

我不希望这种行为成为计算机的默认行为,但它让我有可能改变这些计算机的实现,如下所示:

class SomeComputerImpl  : public ChainableComputer{
/// ...
void compute(Dataset &datas) const override final{
       doPrecomputeOrThrow(Dataset &datas);
}
};
Run Code Online (Sandbox Code Playgroud)

它在应用程序和单元测试中编译并运行良好...如果我在发布模式下编译和运行.

如果我选择Debug,编译工作,应用程序工作,但测试不工作.

我试着理解它会发生什么,但我无法弄清楚可能出现的问题.我想它与链接器有关,并且接口,抽象实现和具体实现是分离DLL的事实,我们在另一个可执行文件中运行这些东西......

我已经尝试过了什么

  1. ChainableComputer直接在test =>中实现一个按预期工作
  2. 使用inline__attribute__(always_inline)打开doPrecomputeOrThrow=>无效果
  3. doPrecomputeOrThrow在namespace中实现(传递Computer*作为参数),在core.dll =>没有效果
  4. doPrecomputeOrThrow在命名空间中实现(将Computer*作为参数传递),在domain.dll =>中按预期工作
  5. doPrecomputeOrThrow在类或命名空间中实现模板,使用Computeras模板参数(见下文)=>按预期工作
  6. doPrecomputeOrThrow在类中实现模板,使用Datasetas模板参数(见下文)=>无效

    //作为Computer(静态或非静态)成员的模板,或//名称空间模板中的模板void doPrecomputerOrThrows(AComputer*c,Dataset&datas);

    // Computer 模板无效的模板,作为模板的成员void doPrecomputerOrThrows(ADataset&datas);

问题

有人知道会发生什么?