我们是否必须将指向非动态分配内存的指针设置为null?

huangapple go评论60阅读模式
英文:

Do we have to set a pointer that does not point to dynamic allocated memory to null?

问题

我很好奇并想知道,在程序结束后,指针是否仍然会指向一个地址。

我曾经学过,我们在释放内存后应该始终将指针设置为null,就像这样:

int* num = new int(2);

// 对num进行一些操作

delete num;
num = nullptr;

但是如果我的指针没有指向动态内存中的地址,而是指向堆栈中的一个常见地址,例如:

int num = 2;
int* pnum = #

// 对pnum进行一些操作

那么我是否也应该将指针设置为null?因为我不希望它继续指向一个地址。

pnum = nullptr;

如果我不将其设置为null,那么在程序运行结束后它是否仍然会指向那个地址?

我曾经学过,在动态内存使用情况下,总是将指针设置为null,但对于指向常见堆栈内存地址的指针呢?

编辑 对于评论中所有那些情绪激动的人,是的,我是一个20岁的新手,还在学习中,是的,你们都很聪明,没有人能够应付你们的智商,因为你们太聪明了,哈哈哈。不要嘲笑我,也不要嘲笑其他人试图帮助的人。对于那些提供简单逻辑解释的人,我感激你们。

英文:

I'm curious and want to know if the pointer will still be hanging around pointing to an address even after the program ends.

I was taught that we should always set a pointer to null after deallocating its memory like this:

int* num = new int(2);

// do something with num

delete num;
num = nullptr;

But what if my pointer was not pointing to an address in dynamic memory but instead it is pointing to a common address in the stack for example:

int num = 2;
int* pnum = #

// do something with pnum

then should I also set the pointer to null? since I don't want it to keep pointing to an address

pnum = nullptr;

And if I don't set it to null will it still be pointing to that address once my program is done running?

I was taught to always set my pointer to null in dynamic memory use case but what about the pointers that point to common stack memory addresses?

EDITH for all those emotional guys in the comments yea im a 20y/o noobie still learning and yes you are so smart no one can deal with your iq cause your so smart hahaha. Stop dissing me nor the others trying to help. To all those giving simple logic explanations i appreciate you.

答案1

得分: 5

你不需要在任何情况下将指针设置为null。你只是把它当作一种安全机制,这样你就不会在以后意外尝试读取无效指针(如果指针为null,而你试图使用它,你会迅速失败并看到问题;如果它指向已释放或其他不再有效的内存,访问可能会“工作”,但属于偶然情况),也不会在再次使用delete时造成损害(在null指针上调用delete是合法的无操作,但在任何其他指针上调用两次将会发生可怕的事情)。

基本上,如果你像这样进行防御性编程,并且指针变量可能会超出其指向的范围(例如,指针在全局内存中,而你给它一个在函数返回时将消失的栈变量的地址),那么当然可以将其设置为null。否则,保留它是没有危险的,只有在特定情况下明确将其设置为null才会带来微小的好处(实际上,如果不再使用它,优化编译器可能会跳过将其设置为null,即使你告诉它这样做,因为从不访问的指针设置为null不会引起可观察的变化)。

要明确一点,回答你“想知道程序结束后指针是否仍然会继续指向一个地址”,除非通过内存映射文件或全局共享内存等显式持久性(在典型的C和C++代码中99%情况下都不适用)将所有程序内存都会在程序实际退出时释放。不管程序退出时指针指向什么,因为在那一点上指针本身将不再存在。

作为进一步的说明:通常处理动态分配内存这种偶尔需要的情况的正确方法是完全避免使用原始指针。从C++14开始,对于动态分配的情况,你的第一个示例简化为:

auto num = std::make_unique<int>(2);

根本不需要delete或null-out。原始指针仅在像你的堆栈案例这样的未受管理的情况下使用,或者在“借用”原始指针的情况下,在函数调用的持续时间内将原始指针放入智能指针中(函数接受一个不打算拥有的原始指针),这意味着你的程序通常可以完全避免使用newdelete,并且将指针设置为null以避免双重delete或使用后释放的问题不再有帮助(智能指针保持它有效,直到智能指针被销毁,在那时它将被清理一次)。

英文:

You don't need to set the pointer to null in either case. You only do it as a safety mechanism, so you don't accidentally try to read through an invalid pointer later (if the pointer is null, and you try to use it you'll die quickly and see the problem, if it's pointing to freed or otherwise no longer valid memory, the access might "work" by accident), nor cause damage if you delete it again (it's a legal no-op to call delete on a null pointer, but calling it twice on any other pointer will do terrible things).

Basically, if you're programming defensively like this, and the pointer variable might outlive what it's pointing to (e.g. the pointer is in global memory, and you give it the address of a stack variable that will disappear when the function returns), sure, null it out. Otherwise, there's no danger to leaving it populated, and only tiny benefits in specific cases to explicitly nulling it out (in practice, if it's not used again, an optimizing compiler might skip nulling it out even if you told it to do so, since there's no observable change from nulling a pointer that is never accessed again).

To be clear, in response to you "want to know if the pointer will still be hanging around pointing to an address even after the program ends", barring explicit persistence via stuff like memory mapped files or global shared memory (none of which applies in 99% of typical C & C++ code), all program memory is released when the program actually exits. It doesn't matter what the pointer was pointing to when the program exits, because the pointer itself ceases to exist at that point.

As a further note: The correct way to handle the occasional need for dynamically allocated memory like this is usually to avoid raw pointers entirely. From C++14 onwards, for the dynamically allocated case, your first example simplifies to:

auto num = std::make_unique&lt;int&gt;(2);

with no need to delete or null-out at all. Raw pointers would only be used in unmanaged cases like your stack case, or "lending" the raw pointer in a smart pointer for the duration of a function call (where the function accepts a raw pointer it doesn't intended to take ownership of), meaning your program can usually avoid using new or delete at all, and null-ing out pointers to avoid double-delete or use-after-free issues is no longer helpful (the smart pointer keeps it valid until the smart pointer gets destructed, at which point it's cleaned up exactly once).

huangapple
  • 本文由 发表于 2023年6月22日 02:55:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76526334.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定