我的应用程序暂停在一行似乎没有任何问题的代码上,但是我的IDE似乎是在该行上挂起并出现错误:
gdb/mi(24/03/09 13:36)(退出.信号'SIGSEGV'收到.说明:分段错误.)
代码行只调用一个没有代码的方法.当您有空引用时,不是分段错误吗?如果是这样,空方法如何具有空引用?
这段代码似乎导致了这个问题:
#include#define BUFFER_SIZE 256 char *buffer; buffer = (char*)GetSomePointer()->SomeStackMemoryString.c_str(); int writeResult = write(socketFD, buffer, BUFFER_SIZE); bzero(buffer, BUFFER_SIZE); int readResult = read(socketFD, buffer, BUFFER_SIZE);
当使用该read(...)
方法的行被注释掉时,问题就会消失.
我已将问题改为指向实际问题,并且已删除所有不相关的代码 - 我也回答了我自己的问题,以便阅读此内容的人明确知道问题所在,请在说"你是"之前阅读我的答案一个白痴!"
首先,通过空指针或引用调用方法严格来说是未定义的行为.但除非呼叫是虚拟的,否则它可能会成功.
虚拟调用需要访问vtable并通过null访问vtable时,虚拟调用虚拟方法(通过指针/引用,而不是使用Class :: Method()调用方式从派生类调用)总是会失败指针/引用是不可能的.因此,您无法通过引用/指针调用空虚方法.
要理解这一点,您需要了解有关代码组织方式的更多信息.对于每个非内联方法,都有一段代码段包含实现该方法的机器代码.
当非虚拟地进行调用时(从派生类或通过引用/指针的非虚方法),编译器确切地知道调用哪个方法(没有多态).所以它只是插入对代码的确切部分的调用,并将该指针作为第一个参数传递.如果通过空指针调用,它也将为null,但您不关心您的方法是否为空.
当虚拟地进行调用(通过引用/指针)时,编译器不知道调用哪个方法,它只知道有一个虚方法表,并且表的地址存储在对象中.为了找到要调用的方法,首先需要取消引用指针/引用,到表中,从中获取方法的地址,然后才调用该方法.读取表是在运行时完成的,而不是在编译期间完成的.如果指针/引用为空,则此时会出现分段错误.
这也解释了为什么无法内联虚拟调用.在编译期间查看源代码时,编译器根本不知道要内联的代码.