C++ 指针段错误没有编译器警告,在先前分配时有效

Han*_*bel 1 c++ pointers segmentation-fault

我很难理解指针以及它们如何/何时失败。所以我制作了一个小程序,它创建一个指针,为其分配一个值,然后打印该值。使用 gcc 和 clang 都可以正常编译,并且在使用 -Wall 开关时不会给出任何警告。为什么它会出现段错误,为什么当我首先为指针分配不同的值时不会出现段错误?我以为我已经初始化了指向某个地方的指针。当我只是声明指针而不进行初始化时,我理所当然地收到编译器警告。但是,在这里我没有收到编译器警告,但它仍然存在段错误。

#include<iostream>

int main(){
  int *b = (int*)  12;  //pointer gets initialized, so it points to somewhere
  //int a = 13;   //works fine when uncommenting this and the next line
  //b = &a;
  *b = 11;
  std::cout << "*b = " << *b << "\n";
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Adr*_*ire 5

指针是保存内存地址的变量。
您“可以”在指针中包含任何内存地址,但是尝试从允许应用程序读取的内存空间之外进行读取,将触发操作系统以段错误错误杀死您的应用程序。

如果允许我打个比喻的话:

您可以在纸上写下您所在国家/地区任何人的地址。但如果你未经许可试图进入那所房子,你很可能会被警察拦住。

回到代码:

int *b = (int*) 123; // ok, you can save what you want.
std::cout << *b << std::endl; // SEGFAULT: you are not allowed to read at 123.
Run Code Online (Sandbox Code Playgroud)

当你取消注释这两行代码时:

int a = 13;
b = &a;
Run Code Online (Sandbox Code Playgroud)

基本上,b不再指向那个禁止的123地址,而是指向 的地址aa在您自己的代码中,并且它的内存不被禁止,因此*b在此之后的访问是允许的。

C++ 并不禁止读取任何硬编码地址(事实上它在某些情况下很有用),但您的操作系统可能不允许您弄乱该内存。

另一方面,编译器能够检测到未经初始化而使用的变量,并可以警告这种情况。这与原始指针无关。