你怎么知道如何释放指针数组?

时间:2015-04-09 22:44:24

标签: c++

如果我有一个像这样的指针数组:

char* p[3];

p[0] = new char;
p[1] = new char[10];
p[2] = &c;

假设我不能使用std::string,我怎么知道如何在不看清楚定义的情况下解除分配?我如何知道在遍历数组时使用deletedelete[],或者它是指向堆栈变量还是堆栈变量?

4 个答案:

答案 0 :(得分:7)

编译器不会在任何地方保存此信息。你必须自己保存。

答案 1 :(得分:4)

简短回答:除非您知道代码编写方式是如何分配的,否则您不会这样做。

长答案:没有(通用的,可移植的方式)来确定如何将某些内容作为具有new char的单个元素或作为具有new char[10];的数组分配或根本不分配。从理论上讲,你可以检查一些地址是否在堆内#34;如果你知道堆的位置,但是没有简单的方法可以知道什么是堆,什么是堆栈以及什么是全局数据而没有对该特定系统的内存布局有相当深入的了解,并在不同的OS上编译相同的代码甚至是相同操作系统的不同处理器架构,而且一切都在变化。要确定单个或数组分配是否更难,如果可能的话[大多数C ++运行时甚至都不会检测到这一点并在您执行char *p = new char[10]; delete p;时抱怨 - 它只会崩溃/行为异常或&# 34;无论如何工作,因为它不重要",取决于你的运气,C ++运行时库设计和机器架构] - 另见下面的进一步讨论。

所以你必须跟踪它作为你的代码的一部分[或根本不编写那样的代码,这是我的偏好],或者使用其他一些构造(智能指针可以工作,矢量可以工作)。

此外:如果您有一种方法可以找出是否有来自堆的东西,您仍然无法确定它是否是原始分配或其他内容"。想象一下:

char *p[2];

p[0] = new char[10];
p[1] = p[0] + 3;

现在,p[1]指向堆内部,但不是它自己的分配,而是指向p[0]分配的位置。所以,基本上,它几乎不可能做到这一点,即使我们知道堆,数据和堆栈内存的位置 - 我们通常不能知道。

作为旁注,人们经常说"堆"好像它是一块连续的记忆。它不是在大多数现代操作系统中,因为有许多不同的方式可以占用特定的内存。它可以作为初始加载可执行文件所加载的代码,数据或堆栈的一部分进行分配。但它也可以是共享库(.so或.dll等)[具有代码和数据空间]的一部分 - 并且它们通常被赋予特定的地址以避免必须重新定位'每个用户的共享库,一块内存可以是内存映射文件或共享内存分配 - 至少有时可以在内存中给出一个特定的地址,因此在中间有一个地址" '堆'记忆区域"。因此,当我们说"堆"时,我们的意思是" OS认为我们可以用来存储东西的任何空闲内存地址,而不是从A到A的一个直线地址B没有洞。它更像是A-B,F-J,M,P和T-V,它们是"堆"。

正如马库斯在评论中提到的那样,有些操作系统有意识地将事情转移到了#34; (地址空间随机化)使非法目的的人更难依赖从一个存储区域到另一个存储区域的距离来滥用堆栈覆盖到"破解"系统。

答案 2 :(得分:0)

如果您知道自己拥有由new[]创建的数组,则只需使用delete[]删除它;这是你必须履行的合同。

如果您不知道某件事是否由您分配,您就会遇到我们称之为内存泄漏的问题,因为您无法释放它,除非您想冒着崩溃程序的风险

答案 3 :(得分:0)

我正在思考它,这是一个非常好的问题,但我认为,你不能。

由于我更习惯于编程C,我认为这是不可能的,因为这些信息必须存储在某个地方(至少在C中)并非如此,据我所知。