分配和释放内存

4
我的问题很简单。我们通常通过声明一个指针并将一块内存分配给该指针来分配内存。假设在代码的某个地方,我使用了

ptr = ptr + 1

然后我使用

free(ptr)

有人能告诉我会发生什么。整个内存块将被释放还是其他情况。我能部分释放内存吗?

4个回答

6
你必须始终传递free所得到的malloc(或realloc)指针的完全相同的副本。如果你不这么做,会导致"行为未定义",这是一个术语,意思是你不能依赖程序以任何可预测的方式运行。在这种情况下,你应该期望它立即崩溃。(如果你不走运,它将损坏内存,导致稍后崩溃,或者更糟糕的是不正确的输出。)
唯一部分释放内存的方法是使用较小的大小进行realloc,但这仅适用于在结尾处修剪,并不能保证被修剪掉的块可供其他分配使用。

1

无法释放内存块的一部分。您唯一能做的就是重新分配该块,给它一个不同的大小。但是这并不能保证该块将落在内存中的相同位置(它可能会被复制到其他地方)。


1

你必须将相同的指针传递给free(),指向malloc()返回的同一个位置。这是因为分配器会保留一种类似于您分配的块的列表(@所有人:如果我说错了,请随时添加/修改),如果您传递给free()的指针与此列表不匹配,free()会报错(可能是“坏内存块”?)。要部分释放内存,您应该使用realloc(),它可以改变该块内存的尺寸,但是速度较慢且效率低下。只有在确定块的新大小或者以后需要更多空间填充时才应使用它。


那么你的意思是分配器保留一个列表,当我们释放包含该块第一个字节地址的指针时,才会释放整个块? - bubble
@bubble 这怎么会有两个赞?你什么时候开始把指针传递给malloc函数了? - David Heffernan
@bubble: 是的,它会记住您为每个块分配了多少字节。 - BlackBear
1
@BlackBear 第一句话现在没问题了,但是后面的都是无意义的。那些都是具体实现细节,因编译器而异。这是未定义行为,没有必要再多说什么了。 - David Heffernan
@David,我投了赞成票,希望我们能就此展开更多讨论。BlackBear非常果断地写了一些我想确认的内容。 - bubble
@bubble,你不需要点赞就可以讨论。无论如何,现在你知道这段代码是错误的了! - David Heffernan

1

malloc(),free()和realloc()不是C语言的一部分。

这些函数是在标准库中定义的。处理它的标准库代码通常被称为“分配器”。因此,实际答案是“取决于C库”。

在Linux上,glibc会使程序崩溃。 在VC++上,C运行时会破坏分配器的状态。

这些库的源代码是可用的,因此您实际上可以设置断点并进入free。


1
将标准C库称为“不属于[C语言]的一部分”并不是错误,但我认为这过于苛求琐碎。 - zwol
不将其称为 C 语言的一部分的原因是因为您可以通过使用不同的库(使用相同的编译器)或编写自己的 malloc / free 代码来自定义行为。我曾经在 98-99 年左右这样做过。这样可以带来诸如编写一个版本以在调试器中打印所有已分配块列表等好处。 - Shamit Verma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接