gcc 为什么redefine __cxa_throw会导致编译错误?

vqlkdk9b  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(213)

我尝试重新定义__cxa_throw来跟踪异常,但是g和clang会生成具有不同函数签名编译错误。

#include <stdexcept>
extern "C" {
  void __cxa_throw(void*, std::type_info*, void(*)(void*)) {}
}
int main() {
  throw std::runtime_error("throw");
}

以上代码是使用clang++-12编译的,没有任何指定的标志,但g++-10生成了这样的错误:

main.cpp: In function ‘int main()’:
main.cpp:6:35: error: invalid conversion from ‘void*’ to ‘std::type_info*’ [-fpermissive]
    6 | int main() { throw std::runtime_error("throw"); }
      |                                              ^
      |                                              |
      |                                              void*

如果将函数签名更改为:

#include <stdexcept>
extern "C" {
  void __cxa_throw(void*, void*, void(*)(void*)) {}
}
int main() {
  throw std::runtime_error("throw");
}

std::type_info*现在变成了void*,g++-10和clang++-12已编译。
但如果我在代码中插入cxxabi.h

#include <stdexcept>
#include <cxxabi.h>
extern "C" {
  void __cxa_throw(void*, void*, void(*)(void*)) {}
}
int main() {
  throw std::runtime_error("throw");
}

g++-10仍在编译,而clang++-12生成此错误:

main.cpp:4:8: error: conflicting types for '__cxa_throw'
  void __cxa_throw(void*, void*, void (*) (void *)) {}
       ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/cxxabi.h:616:3: note: previous declaration is here
  __cxa_throw(void*, std::type_info*, void (_GLIBCXX_CDTOR_CALLABI *) (void *))
  ^
1 error generated.

所以这意味着cxxabi.h中第二个参数的类型是std::type_info*,但是为什么g++-10不能编译第一个代码呢?
我的工作环境是wsl 2,使用的是Ubuntu 20.04,g10.3.0,clang12.0.0。

f4t66c6m

f4t66c6m1#

我认为错误消息表明gcc将void*作为第二个参数传递,gcc的__cxa_throw同样接受void*,而对于clang,类型则是std::type_info*。因此,我将尝试类似如下的操作:

#include <stdexcept>
#include <cxxabi.h>
#include <stdlib.h>

extern "C" {

#if !__clang__
  void __cxa_throw(void*, void*, void(*)(void*)) { abort(); }
  //abort to avoid warnings about noreturn functions
#else
  void __cxa_throw(void*, std::type_info*, void(*)(void*)) { abort(); }
  

#endif

}
int main() {
  throw std::runtime_error("throw");
}

在gcc和clang上编译时不会出现错误:https://gcc.godbolt.org/z/a9qzrvxqT

相关问题