C 和 C++:释放已分配指针的一部分

Posted

技术标签:

【中文标题】C 和 C++:释放已分配指针的一部分【英文标题】:C and C++: Freeing PART of an allocated pointer 【发布时间】:2009-08-20 08:29:42 【问题描述】:

假设我分配了一个指针来保存 4096 字节。如何释放 C 中的最后 1024 个字节?在 C++ 中呢?相反,如果我想释放 first 1024 个字节,并保留其余部分(两种语言)怎么办?从中间解除分配怎么样(在我看来,这需要将它分成两个指针,在解除分配区域之前和之后)。

【问题讨论】:

不确定,但使用正确大小的“假”指针,删除或释放你想要的指针应该可以解决问题,至少需要 2 个指针。 @claferri。那是未定义的行为。您只能 free() 从 malloc/realloc 返回的指针 - 否则,free() 怎么知道要释放多少? @roddy : 你是对的 :) 【参考方案1】:

不要尝试和事后猜测内存管理。它通常比你聪明;-)

您唯一可以实现的就是第一个“释放”最后 1K 的场景

char * foo = malloc(4096);

foo = realloc(foo, 4096-1024);

但是,即使在这种情况下,也不能保证“foo”不会改变。您的整个 4K 可能会被释放,并且 realloc() 可能会将您的内存移动到其他地方,从而使您可能持有的任何指向它的指针无效。

这对 C 和 C++ 都有效 - 但是,在 C++ 中使用 malloc() 会产生不好的代码气味,大多数人会希望您使用 new() 来分配存储空间。并且用 new() 分配的内存不能被 realloc()ed - 或者至少不能以任何可移植的方式。 STL 向量将是 C++ 中更好的方法

【讨论】:

【参考方案2】:

您没有“分配用于保存 4096 字节的指针”,您有一个指向已分配 4096 字节块的指针。

如果您的块是用malloc() 分配的,realloc() 将允许您减小或增加块的大小。不过,块的起始地址不一定保持不变。

您无法更改malloc'd 内存块的起始地址,这正是您的第二种情况所要求的。也无法拆分 malloc'd 块。

这是malloc/calloc/realloc/free API 的限制——并且实现可能依赖于这些限制(例如,在开始地址之前保留有关分配的簿记信息,这会使移动起始地址变得困难。)

现在,malloc 并不是唯一的分配器——您的平台或库可能会提供其他分配器,或者您可以编写自己的(通过 mallocmmap、@ 从系统获取内存) 987654332@ 或其他机制),然后以您想要的任何方式将其分发给您的程序。

对于 C++,如果您使用 std::malloc 分配内存,则适用上述信息。如果您使用newdelete,则您正在为对象分配存储空间和构造对象,因此更改已分配块的大小没有意义——C++ 中的对象是固定大小的。

【讨论】:

【参考方案3】:

如果你有n字节的mallocated内存,你可以reallocm字节(其中mn),从而丢弃最后的n-m字节。

要从头扔掉,你可以malloc 一个新的、更小的缓冲区和memcpy 你想要的字节,然后free 原来的。

使用 C++ newdelete 也可以使用后一个选项。它还可以模拟第一个realloc 案例。

【讨论】:

"malloc/memcpy/free" 是 realloc 在内部的实现方式。 我同意 realloc 通常会返回(相同的)第一部分,但它是 realloc 的官方要求吗?我认为这可能是可以将数据移动到新位置的实现。 想象一个智能的重新分配方案,其中跟踪分配的历史模式......如果最近有 4096 字节的分配请求,最好将收缩块移动到其他地方以释放这 4K堵塞。在这种情况下,地址会改变。 realloc 返回一个指向新内存区域的指针,所以程序员应该使用它。不管它是否改变。 放弃开头的另一种方法是使用 memmove() 将数据移回,然后使用 realloc() 到所需的大小【参考方案4】:

您可以使用 realloc() 缩短它。我认为其余的都不可能。

【讨论】:

【参考方案5】:

您可以使用 realloc() 来明显缩短内存。请注意,对于某些实现,这样的调用实际上不会做任何事情。您不能释放块的第一位并保留最后一位。

如果您发现自己需要这种功能,您应该考虑使用更复杂的数据结构。数组并不是所有编程问题的正确答案。

【讨论】:

我正在实现一个内存系统,因此我希望在保持便携性的同时获得尽可能低的访问级别。【参考方案6】:

http://en.wikipedia.org/wiki/New_(C%2B%2B)

总结:与 C 的 realloc 相比,它 无法直接重新分配 用 new[] 分配的内存。延长 或减小块的大小,一个 必须分配一个足够的新块 大小,复制旧内存,然后 删除旧块。 C++ 标准 库提供了一个动态数组 可以扩大或减少其 std::vector 模板。

【讨论】:

以上是关于C 和 C++:释放已分配指针的一部分的主要内容,如果未能解决你的问题,请参考以下文章

C++ 对象的动态建立 & 释放

c++中new和delete的用法

[c++基础] delete 和 delete []的区别

被释放的指针未分配,即使它之前已分配

在C语言进行编程中,为啥要释放旧内存?

C ++释放共享库中动态分配的内存导致崩溃