【问题标题】:C++ exceptions binary compatibilityC++ 异常二进制兼容性
【发布时间】:2010-04-12 02:53:53
【问题描述】:

我的项目使用 2 个不同的 C++ 编译器,g++ 和 nvcc(cuda 编译器)。 我注意到从 nvcc 对象文件抛出的异常没有在 g++ 对象文件中捕获。

C++ 异常在同一台机器上是否应该是二进制兼容的? 什么会导致这种行为?

try { kernel_= new cuda:: Kernel(); }
catch (...) { kernel_= NULL; }

// nvcc object
cuda:: Kernel:: Kernel () {
  ...
  if (! impl_) throw;
}

其他一切似乎都有效(C++ 对象、运算符)。老实说,我不太了解异常,所以上面的代码可能有错误。

【问题讨论】:

    标签: c++ exception binary-compatibility


    【解决方案1】:

    很抱歉在一个晚上给你两个“不”的答案,但是“不”,C++ 异常(或与此相关的类)没有标准的二进制布局。尝试在两个不同的编译器之间使用 C++ 类/异常会破坏One Definition Rule。

    您可以通过仅允许目标文件之间的 C API 来解决此问题(因为 C 具有标准 ABI - 应用程序二进制接口),或者您可以使用一个编译器或其他。但是,我不确定 NVCC 是否可以实现最后一点。

    回答问题编辑:其他一切似乎都有效(C++ 对象、运算符):在绝大多数情况下,似乎有很多东西有效.这并不意味着它们不会调用未定义的行为。

    【讨论】:

    • 我发现大多数事情似乎都有效,这很令人惊讶。通常,不同的编译器会故意有不同的名称修饰方案,以便您可以及早避免这些问题,即在编译时或链接时。
    • @Ken:这是真的;但异常处理并非如此——也就是说,因为这是编译器差异很大的地方之一。例如,MSVC++ 在 NT 的 SEH 之上构建其异常支持,而 GCC 使用某种形式的基于表的实现。
    • 我的意思是我很惊讶大多数东西似乎都可以工作,因为如果两个不同的编译器以某种方式(无论多么微妙)实现不同的 ABI,那么我希望它们故意有不同的名称修改方案,这样您就不会犯将来自两个不同编译器的二进制文件组合在一起的错误。见parashift.com/c++-faq-lite/compiler-dependencies.html#faq-38.9
    【解决方案2】:

    nvcc 是普通 c++ 编译器的包装器,基本上是将 cuda 语法转换为可编译的东西的预处理器。您可以通过--verbose 标志查看它使用的编译器。

    例如在我的机器上编译

    // test.cpp
    int main(){return 0;}
    

    nvcc -v 给予

    #$ _SPACE_= 
    #$ _MODE_=DEVICE
    #$ _HERE_=/usr/local/cuda/bin
    #$ _THERE_=/usr/local/cuda/bin
    #$ TOP=/usr/local/cuda/bin/..
    #$ PATH=/usr/local/cuda/bin/../open64/bin:/usr/local/cuda/bin/../bin:/Library/Frameworks/Python.framework/Versions/Current/bin:/Users/me/bin:/usr/local/aspell/bin:/usr/local/noweb:/usr/local/icon/bin:/usr/local/dmd/bin:/usr/local/cuda/bin:/usr/local/sed/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin
    #$ INCLUDES="-I/usr/local/cuda/bin/../include"  
    #$ LIBRARIES=  "-L/usr/local/cuda/bin/../lib" -lcudart
    #$ CUDAFE_FLAGS=
    #$ OPENCC_FLAGS=
    #$ PTXAS_FLAGS=
    #$ gcc -c -x c++ "-I/usr/local/cuda/bin/../include"   -I. -m32 -malign-double -o "/tmp/tmpxft_000010af_00000000-1_test.o" "test.cpp" 
    #$ g++ -m32 -malign-double -o "a.out" "/tmp/tmpxft_000010af_00000000-1_test.o"   "-L/usr/local/cuda/bin/../lib" -lcudart
    

    使用此处列出的相同编译器/标志应该可以提供二进制兼容性

    【讨论】:

      【解决方案3】:

      C++ 标准没有指定任何东西的二进制形式,更不用说异常了。您没有理由期望它会起作用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-10-11
        • 2020-05-12
        • 2011-08-03
        • 1970-01-01
        • 2011-08-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多