为什么在使用链接时优化时未捕获此抛出的对象?

时间:2019-06-20 04:23:57

标签: c++

假设我在共享库中有一个函数抛出了一些对象,并且有一个主要的可执行文件调用该函数并试图捕获该对象,例如

decl.h

#ifndef DECL_H
#define DECL_H

void pitch();

struct MyException {
    MyException();
    MyException(const MyException&);
    ~MyException();
};

#endif

pitch.cpp

#include "decl.h"

MyException::MyException() {}
MyException::MyException(const MyException&) {}
MyException::~MyException() {}


void pitch() {
    throw MyException();
}

main.cpp

#include <stdio.h>
#include "decl.h"

int main() {
    try { pitch(); }
    catch (MyException& e) { printf("MyException()\n"); }
    catch (...)            { printf("[unknown exception]\n"); }
}

Makefile

all:
    $(CXX) -shared -fPIC $(CXXFLAGS) $(LTO) pitch.cpp -o libpitch.so
    $(CXX) -g $(CXXFLAGS) $(LTO) main.cpp -L. -lpitch
    ./a.out

如果我在不进行链接时优化的情况下进行编译,那么一切都很好:

CXXFLAGS="-g -O2" LTO=""      make
c++ -shared -fPIC -g -O2  pitch.cpp -o libpitch.so
c++ -g -g -O2  main.cpp -L. -lpitch
./a.out
MyException()

但是一旦我打开链接时优化,就不再捕获抛出的对象:

CXXFLAGS="-g -O2" LTO="-flto" make
c++ -shared -fPIC -g -O2 -flto pitch.cpp -o libpitch.so
c++ -g -g -O2 -flto main.cpp -L. -lpitch
./a.out
[unknown exception]

这是预期的行为吗?这是我的C ++代码中的问题还是其他问题?这是在macOS 10.14.5上:

$ c++ -v
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

1 个答案:

答案 0 :(得分:0)

这不是预期的行为。

我在Linux(ubuntu)上使用gcc 4.x,5.x,6.x,7.x和8.x以及clang 6.0对其进行了测试。 -O2 -flto一切正常。

不幸的是,由于我无法复制它(我没有Mac),所以我无法告诉您出了什么问题,但这不是您的代码恕我直言。

编辑:

我不能很清楚地说您的代码“没有错”(尽管我按照您的说明进行了测试-但是,我需要将LD_LIBRARY_PATH="."设置为./a.out才能正常工作(所以也许您正在加载其他库?))而没有向您展示我如何编写以上代码:

// decl.h:

#pragma once

#include <exception>

void pitch();

struct MyException : public std::exception
{
};

// pitch.cpp:

#include "decl.h"

void pitch()
{
  throw MyException();
}

// main.cpp:

#include "decl.h"
#include <iostream>

int main()
{
  try
  {
    pitch();
  }
  catch (MyException const& e)
  {
    std::cout << "MyException(): " << e.what() << std::endl;
  }
  catch (...)
  {
    std::cerr << "[unknown exception]" << std::endl;
  }
}