指向函数本地结构的指针的范围和生存期
Posted
技术标签:
【中文标题】指向函数本地结构的指针的范围和生存期【英文标题】:scope and lifetime of a pointer to struct which is local to a function 【发布时间】:2021-09-06 22:03:04 【问题描述】:在下面的代码中,我在最后一个节点处插入。它工作正常。 但我的疑问是因为我最后声明了 Node *;本地,因此每当进行新调用时,都会创建一个新的指针变量,并在函数终止后从内存中删除前一个变量。那么 Node * 是怎么来的?是否保留了上一次调用的地址,因为每次都会重新创建?
第一;是指向链表第一个节点的指针,全局声明。
void insertLast(int x)
Node *last;
Node *q=new Node;
q->data=x;
q->next=NULL;
if(first==NULL)
first=last=q;
else
last->next=q;
last=q;
insertLast(2);
insertLast(5);
insertLast(7);
display(first);
output:
2 5 7
【问题讨论】:
请在问题中包含您的代码的minimal reproducible examplelast->next=q;
行是未定义的行为,因为此时 last
未初始化。
那么为什么 Node * 是最后一个?正在保存上一次调用的地址 - 未定义的行为。它很可能只起作用,因为您连续进行调用并且值保存在寄存器/堆栈中未清除。如果您在display
之后再添加一个insertLast
调用,它可能会崩溃。
@463035818_is_not_a_number 我已经更新了帖子。请再次检查。
@Yksisarvinen 我在显示后尝试添加。仍然可以正常工作。
【参考方案1】:
更简单的例子,同样的效果:
#include <iostream>
void DONT_DO_THIS(bool init)
int x;
if (init) x = 42;
else std::cout << x << "\n";
void foo()
int y = 0;
int main()
DONT_DO_THIS(true);
DONT_DO_THIS(false);
DONT_DO_THIS(false);
foo();
DONT_DO_THIS(false);
在进一步阅读之前,请尝试找出这段代码的输出。
你下定决心了吗?
你知道输出是什么吗?
无论您期望此代码打印什么,它都是错误的。该代码具有未定义的行为并且可以产生任何输出。使用 gcc 11.1,这是我得到的输出:
42
42
0
未初始化时从局部变量x
读取是未定义的行为。你不能那样做!如果您无论如何都这样做,一种可能性是下次您调用该函数时,42
仍存储在寄存器中,而x
恰好具有该值。事实上x
在这种情况下没有任何价值。据说它有一个你无法读取的不确定值。
打开优化 (-O3
) 时,输出如下:
0
0
0
很可能编译器意识到代码有 UB 并优化掉所有无意义的代码。
无论你得到什么输出,任何输出都符合 C++ 标准,因为标准没有规定编译具有未定义行为的代码应该是什么结果。
TL;DR:始终初始化变量。永远不要从未初始化的变量中读取。具有未定义行为的代码似乎可以工作,但它必须被修复。
【讨论】:
以上是关于指向函数本地结构的指针的范围和生存期的主要内容,如果未能解决你的问题,请参考以下文章
在c语言中 分别从变量的作用域和生存期来分析变量各都有哪些种类