关于C 的动态内存分配
Regarding dynamic memory allocation in C++
假设我通过p1
的动态内存分配如下,
int* p1 = new int;
*p1 = 1;
我知道p1
引用的内存可以通过
delete p1;
p1 = nullptr;
但是我想知道是否还有另一个指向1
的指针p2
,我可以delete
这个指针以释放内存吗?Pointer p1
会发生什么?另外,p1
和p2
之间的关系实际上是什么?例如,
int* p1 = new int;
*p1 = 1;
int* p2 = p1;
// Can I delete p2 like this? And what would happen to p1?
delete p2;
p2 = nullptr;
您可以删除p2
,但是删除p1
将导致不确定的行为和可能的分割故障。
它是这样的工作:
- 在某个地址分配内存。
-
p1
和p2
指向此内存位置。 - 一旦删除了
p2
-p1
仍指向此内存位置。没有泄漏,一切都还好 - 只是不要退出p1
。您可以自由执行p1 = nullptr
,但不能*p1 = 1
。另外,您无法删除p1
,因为它已经被删除,并且您可能会捕获Segfault。
您在(旧)C 中描述一个非常清楚的问题:当几个指针指向相同的动态内存时,它删除了它?p>如果您同时删除p1
和p2
,则删除具有不确定行为的内存(在最好的情况下是崩溃),如果您删除p1
或p2
,并且您继续使用其他指针使用内存 - 您正在使用 - 您正在使用悬空指针,这是不确定的行为(在最好的情况下,崩溃)。您需要确保删除一个指针时 - 您不要在其他指针中使用该内存。
c 11引入了解决此问题的标准方法:使用自我计数指针,只有最后一个指针删除内存:
auto p1 = std::make_shared<int>(0);
auto p2 = p1;
现在,最后一个指针Alive将删除分配的内存,您不必担心删除什么的人。
以及指针P1会发生什么?另外,P1和P2之间的关系实际上是什么?
他们的基本关系是他们指向分配后int* p2 = p1;
后从动态内存分配获得的相同地址。
因此,删除它们中的任何一个都可以释放分配的内存。将其中一个设置为nullptr
不会影响另一个。
因此,您剩下的悬挂指针无法安全删除。
您可以删除p1
或p2
。没有区别。但是你不应该删除两者。另外,一旦删除了一个,就不应使用另一个。程序员对此负责。该语言本身不会提供任何帮助。这里有很多不同的方法来编写不良代码。
有几种处理此操作的技术/模式。经常将智能指针用于此。查看std :: shared_ptr文档。请勿使用过时的auto_ptr
。
我最喜欢的模式是"所有权"。这意味着一个指针"拥有"分配,而所有其他指针都只使用。这需要在编程时进行某些纪律,但是一旦应用了这项工作,结果代码就清晰又简单。例如:
class MyClass
{
public: ~MyClass() { for(char *p: myStringsDict) delete p; }
private:
std::unordered_set<char*> myStringsDict;
};
看这堂课很明显(尽管添加适当的评论很高兴)它拥有字符串字典,只要存在此类的实例,这些字符串就有效。这些指针可以用于该类拥有的结构中,它们可以作为参数传递给函数等。很明显,何时不再使用它们。
在服务器编程中,当多个线程运行时,双重删除可能非常危险且难以跟踪。因为删除第一个指针后,内存变得自由,并且可以在其他线程上分配其他目的。当第二个指针被释放时,可能会删除有效的分配,而其他代码对此一无所知,并且正在继续使用此内存。
解决所有这些问题的很好的解决方案是垃圾收集。当使用明确分配时,程序员需要以这种方式应用额外的精力。
让我们探索房地产类比,在这里记忆扮演土地和指针的作用并不是很难以充当地址。
指针变量是一个黄色的邮政注释。您可以在上面写一个街道地址。从免费商店分配的变量是某个地址的一块土地。
int *p = new int;
您要求城市在某个地方找到一块未使用的土地,并将标题分配给您自己。您将其街道地址写在黄色音符上。
*p = 1;
您在该地址建造一个整洁的小房子。
int *q = p;
您制作黄色音符的副本。你忘记了一段时间。
delete p;
您拆除了建筑物,放弃了对土地的权利。这座城市可以将其分配给其他人。也许有人想在那里建造另一个小建筑物,或者铺设铁路轨道或建立鲨鱼池。请注意,这对您的任何黄色音符都没有任何作用。
p = nullptr;
您擦拭黄色音符。您的其他黄色音符徘徊。
*q = 2;
您找到了另一个黄色的音符,请阅读一个曲折地址,并假设土地是您的。不好的举动。您继续在别人的土地上建造一个整洁的小房子。新主人不在乎(他们无法了解)。明天,他们可能会拆除您的建筑物,并将自己的建筑物置于适当的位置,或者用火车淹没您,或者在您身上倾倒100000吨水和3个Makos。那真是不愉快!不要触摸什么不是您的。
使用新的delete分配动态存储器时,只要您使用新的免费创建P1,则应通过delete释放它它使用删除。您将p2声明为指向相同内存的指针,如果要在 p1
上免费呼叫删除p2
,则可以将P1指向P1点,但是可以通过在p1或p2上调用delete来释放内存。
如果您在p1上调用删除
delete p1;
*p2 = 1;
将导致不确定的行为。
- Win32编译器选项和内存分配
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 当需要超过16GB的连续内存时,内存分配失败
- 尝试摆脱任何堆内存分配
- 以下代码执行哪种内存分配(动态或静态)?
- 开放 CV 中的动态内存分配,用于视频处理
- 为什么类和 main() 函数中也有动态内存分配
- 使用 NTAllocateVirtualMemory 和 GetProcAddress 的内存分配问题不起作用
- C++:矢量分配器行为、内存分配和智能指针
- 介于 [固定数组] 和 [带内存分配的指针] 之间的性能
- Linux C++ 中的页面对齐内存分配
- 整数内存分配/释放
- 将内存分配返回值强制转换为 TYPE 数组
- C++程序什么都不做,但瓦尔格林德显示内存分配
- 给定特定内存地址的数组的动态内存分配
- 如何完成内存分配
- 我刚刚了解了C++中的动态内存分配
- 在先前调用 string::find 后添加内存分配和内存集会导致它返回 npos.为什么?
- 对于堆上的页面对齐内存分配是否有任何优化或不同的 API?
- 无法删除布尔动态内存分配