为什么gcc 4.7.0在这个代码上给了我一个segfault,而在线视频(gcc 4.5.1)没有
Why is gcc 4.7.0 giving me a segfault on this code while online ideone(gcc 4.5.1) doesnt?
我有以下代码(仅适用于gcc):
#include <iostream>
#include <cstdlib>
#include <string>
#include <typeinfo>
#include <cxxabi.h>
const std::string demangle (const char* name) {
int status = -4;
char* res = abi::__cxa_demangle(name, 0, 0, &status);
const char* const demangled_name = (status == 0) ? res : name;
std::string ret_val(demangled_name);
std::free(res);
return ret_val;
}
template <typename T>
const std::string getname (T x)
{
return demangle(typeid(x).name());
}
int main()
{
std::add_const<int>::type *p = static_cast<const int *>(0);
std::cout << getname(*p) << std::endl;
}
在我的本地计算机上(使用gcc 4.7.0(实验性),它崩溃了(使用gdb运行会产生segfault)。然而,使用ideone.com,它可以按预期打印"int"。下面是示例链接。此外,去掉模板并调用demangle(typeid(x).name())
直接解决了问题,那么模板有什么问题呢?
编辑我忘了包含解决问题的type_traits
标头(doh!),但我仍然想更好地了解发生了什么。
std::add_const<int>::type *p = static_cast<const int *>(0);
p
是一个空指针,对其进行去引用(即*p
)调用会产生未定义的行为(UB)。你很幸运,它给了segfault。由于它实际上是UB,所有编译器(和所有版本)都可能不会给出segfault,因为这就是UB的意思,即任何事情都可能发生。
你为什么不试试这个呢:
std::cout << getname(int()) << std::endl;
这里有一个微妙的问题:这是一个评估问题。
通常,取消引用空指针是未定义的行为;然而,有一种极端情况(至少在gcc上),即在p
为null的情况下调用typeid(*p)
是有效的表达式。
因此,这里的问题在于您的间接级别:
int* p = 0;
getname(*p); // p is null, *p invokes undefined behavior
typeid(*p).name(); // p is null, but it's probably okay in `typeid`
// because it's an unevaluated operand here
对于那些有兴趣深入研究的人,typeid
表达式在§5.2.8(C++11)中有详细描述。
2/当
typeid
应用于类型为多态类类型(10.3)的glvalue表达式时,结果指代std::type_info
对象,该对象表示glvalue所指的最派生对象(1.8)(即动态类型)的类型。如果glvalue表达式是通过将一元*
运算符应用于指针而获得的,并且指针是空指针值(4.10),则typeid
表达式抛出std::bad_typeid
异常(18.7.3)
好的,如果p
指向多态类,那么定义typeid(*p)
。。。在这种情况下,它会抛出。
3/当
typeid
应用于多态类类型的glvalue以外的表达式时,结果指代表示该表达式的静态类型的std::type_info
对象。Lvalue到右值(4.1)、数组到指针(4.2)和函数到指针(4.3)的转换不应用于表达式。如果表达式的类型是类类型,则应完全定义该类。表达式是未赋值的操作数(第5条)。
有趣的是,没有提到非多态类的空指针。我怀疑未赋值的操作数是允许这样做的原因,但尚未找到引文。
6/如果在使用
typeid
之前未包含标头<typeinfo>
(18.7.1),则程序格式不正确。
似乎不需要诊断。至少在gcc上,我认为这是一个警告。
- CMake项目Boost库错误:Boost/config/compiler/gcc.hpp:165:10:致命错误:cs
- C++中带有List类的迭代器Segfault
- 奇怪的结构&GCC&clang(void*返回类型)
- GCC本机矩阵运算库
- PowerPC ppc64le上的Gcc Woverloaded虚拟错误
- gcc和c++17的过载解析失败
- 数据成员SFINAE的C++17测试:gcc vs clang
- GCC对可能有效的代码抛出init list生存期警告
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 使用 GCC 卸载的 OpenMP 卸载失败,并出现"Ptx assembly aborted due to errors"
- 为什么与常规GCC不同,即使有"学究性错误",MinGW-GCC也能容忍丢失的返回类型
- 使用gcc从静态链接的文件中查找可选符号
- 普通环路未使用gcc 4.8.5自动矢量化
- 超级怪异的gcc 4.7 segfault——Bug
- gcc segfault在编译嵌套参数包代码上
- 带有GCC的%s segfault的vsnprintf
- std::为GCC中的默认参数segfault映射带有空大括号初始值设定项的参数
- 静态初始化期间将 gcc 构建的 Boost 链接到英特尔 C++ 编译程序时出现 Segfault
- C++:所有升压路径操作segfault(OSX/GCC)
- 为什么gcc 4.7.0在这个代码上给了我一个segfault,而在线视频(gcc 4.5.1)没有