如果在NULL指针取消引用之前使用cout似乎不起作用

时间:2016-11-21 06:17:39

标签: c++ c++11 pointers nullpointerexception

我有以下C ++代码。我要求NULL指针的内存值。我的意思是,我正在做类似 NULL-> 类型的操作。 我知道这是一个错误。我在函数'funct'中执行此操作,我在调用此函数之前打印错误之前一词。程序运行时,必须打印此消息,然后必须发生错误。相反,直接发生错误。为什么会这样?

是否因为print语句和funct执行是独立的,因此它们发生在不同的线程/核心中,因此错误在打印之前?

#include <iostream>
#include <string>
using namespace std;

struct A 
{
   int a;
};

void funct(int a)
{

  A *obj;
  obj = NULL;
  cout<<"Value is  "<<obj->a;

}


int main()
{

   cout<<"Before Error";
   funct(205);

   getchar();
   cout<<"\n END \n";

}

4 个答案:

答案 0 :(得分:1)

这种情况正在发生,因为cout输出默认是缓冲的。您的程序在有机会刷新输出缓冲区之前会遇到分段错误。您可以使用以下命令禁用缓冲:

std::cout.setf(std::ios::unitbuf);

如果您将其放在main()的顶部,则会在segfault消息之前看到输出。您可能不希望禁用缓冲,这会影响性能,但在这种情况下,它会显示消息确实正在写入。

您也可以一次性刷新缓冲区:

cout<<"Before Error";
std::cout.flush();
funct(205);

答案 1 :(得分:1)

取消引用空指针是未定义的行为。

程序的行为完全未定义。

当你有未定义的行为时,编译器可以而且会做一些疯狂的事情。

关于具有未定义行为的程序的推理是徒劳的。

话虽如此,您可能希望每次调用<< endl时都要cout,因为这会将缓冲区刷新到标准输出。这可能(或可能不完全取决于编译器和正在进行的优化!)对程序的行为产生某种影响。但这只是猜测。它甚至可能不会做你想要的。它可能会将随机信息发送到stdout。关于未定义行为的推理非常困难。

例如,在GCC 6.2上使用-O3在汇编级别上探索代码时,字符串'\ n END \ n'在程序集中根本不存在(相关但不完整的程序集在下面重现)。 / p>

funct(int):
        mov     eax, DWORD PTR ds:0
        ud2
.LC0:
        .string "Before Error"
main:
        mov     edi, OFFSET FLAT:std::cout
        sub     rsp, 8
        mov     esi, OFFSET FLAT:.LC0
        call    std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)
        mov     edi, 205
        call    funct(int)
        sub     rsp, 8
        mov     edi, OFFSET FLAT:std::__ioinit
        call    std::ios_base::Init::Init()
        mov     edx, OFFSET FLAT:__dso_handle
        mov     esi, OFFSET FLAT:std::__ioinit
        mov     edi, OFFSET FLAT:std::ios_base::Init::~Init()
        add     rsp, 8
        jmp     __cxa_atexit

答案 2 :(得分:0)

行为可能因平台(linux或Windows)和编译器设置而异。在linux上,printf / cout在执行语句后不会立即显示。 您可能希望使用std :: cout.flush();或者把结束。

答案 3 :(得分:0)

事实上,邮件已打印,您可以使用以下方式进行检查:

cout << "Before Error";
Sleep(5000);
funct(205);

5秒后,错误将被捕获。