【问题标题】:c++ segfault and pointers confusion (I have the feeling I'm missing something terribly obvious)c++ 段错误和指针混淆(我感觉我错过了一些非常明显的东西)
【发布时间】:2021-06-18 14:46:26
【问题描述】:

我是一名刚接触 C++ 的 Python 程序员。目前在尝试使用指针时出现段错误。有人可以解释这种行为吗?我怀疑cout 有一些我不理解的重要内容。

#include<iostream>
using namespace std;

int main() {
    int var; // declaration
    cout << "var declared" << endl;
    cout << "var             : " <<  var << endl;
    cout << "&var            : " << &var << endl;

    var = 10; // initialization
    cout << "\nvar initialized" << endl;
    cout << "var             : " <<  var << endl;
    cout << "&var            : " << &var << endl;

    int* ptr; // declaration
    cout << "\nptr declared" << endl;
    cout << "ptr             : " <<  ptr << endl;
    cout << "*ptr            : " << *ptr << endl;
    cout << "&ptr            : " << &ptr << endl;

    ptr = &var; // initialization
    cout << "\nptr initialized : " << endl;
    cout << "ptr             : " <<  ptr << endl;
    cout << "*ptr            : " << *ptr << endl;
    cout << "&ptr            : " << &ptr << endl;

    return 0;
}

使用此编译器命令

g++ --std=c++14 main.cpp -o main_exec;

此代码产生以下输出

var declared
var             : 0
&var            : 0x7fff55724478

var initialized
var             : 10
&var            : 0x7fff55724478

ptr declared
ptr             : 0x0
[1]    82727 segmentation fault  ./main_exec

这段代码显然可以编译,但在运行时会产生段错误。

我尝试过的事情 我已经尝试将包含*ptr 的行和包含&amp;ptr 的行注释掉的组合,短篇小说是一些组合不会产生段错误。看来我可以使用*ptr 1 次而不是与&amp;ptr 结合使用

【问题讨论】:

  • 这与cout无关。当ptr 指向任何内容时(因为它没有被初始化),您正试图访问ptr 指向的值。那是未定义的行为。
  • 谢谢@Yksisarvinen 使用int* ptr = new int; 留出一个整数值的内存是解决这个问题的合法方式,还是以某种方式错过了重点?有什么理由不总是这样做或至少默认这样做吗?
  • new 在堆上分配内存,使用完后你有责任delete 它。在现代 C++ 中,您通常希望避免使用 new(以及一般的原始指针)。如果没有充分的理由使用它,则不应使用它。
  • var = 10; // initialization 不,不是,这是任务。 ptr = &amp;var; // initialization 不,不是,这是任务。初始化和赋值之间的区别在于你缺少什么。
  • @StephenM.Webb 很好,也感谢您澄清这一点。我在想我错过了什么。

标签: c++ pointers segmentation-fault cout


【解决方案1】:

您声明了一个指向整数的指针,但没有用任何指针初始化或分配它(即指向整数变量的内存地址)。

int* ptr; // declaration

上面那行说,ptr 是一个指针(它会指向一个整数变量的内存地址)。在您的情况下,它只是说它是一个指针,它所指向的内容没有定义。

当你击中这条线时,

cout << "*ptr            : " << *ptr << endl;

这里 *ptr 的意思是,在地址(实际存储该值的地址)处获取值,并由 ptr 指向。但是 ptr 没有任何意义。所以你试图以一种不允许的方式访问内存,这会导致分段错误。

请记住,指针是变量,因为它们的值存储另一个变量的内存地址。

int *ptr; // would store memory address of an integer type variable.
int a = 5; // would store an integer variable.
ptr = &a; // Here &a gets the address of variable a and stores in *ptr
cout<<*ptr // Here *ptr gets the value of variable whose memory address is pointed to by *ptr.

编辑

如果 int * ptr = new int; 有效,则回答问题。

是的,它会为您保留一个内存位置,并允许您稍后在该位置存储值,如下面的代码所示,

int* ptr = new int;  // gets memory address and assigns to *ptr
*ptr = 5; // assigns value 5 to the memory being pointed by *ptr
cout<<*ptr; // output 5

但是,除非您有特殊需要,否则您不应该这样做。

  • 变量为您保留记忆,并为您提供您选择的友好变量名称。
  • 按照评论部分的建议,您使用 new 创建的任何内容都不会自动删除。
  • 与此相反,变量在超出范围(块、函数、循环等)时会被自动删除

【讨论】:

  • 感谢您的明确解释。当我有足够的“声誉”来投票时,我会投票。鉴于您的解释,这很明显。我假设通过声明int* ptr;,行为将是留出适当的内存。在这种情况下是否没有分配内存?通过使用 int* ptr = new int; 分配 int 的内存,我能够“避免错误”
  • 使用int* ptr = new int; 是一种合法的方式吗?有什么理由不总是这样做或至少默认这样做吗?
  • @CWW 更新了答案,最后一节是关于您关于使用 new 的问题。
  • 感谢您的更新!这更清楚了,我还有很多关于指针的知识要学习,但我认为这让我可以开始很好地管理它们,以应付现在。
猜你喜欢
  • 2019-09-18
  • 1970-01-01
  • 1970-01-01
  • 2010-10-17
  • 2014-06-07
  • 2015-07-15
  • 2010-09-06
  • 2019-03-12
  • 1970-01-01
相关资源
最近更新 更多