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
并不是唯一的分配器——您的平台或库可能会提供其他分配器,或者您可以编写自己的(通过 malloc
、mmap
、@ 从系统获取内存) 987654332@ 或其他机制),然后以您想要的任何方式将其分发给您的程序。
对于 C++,如果您使用 std::malloc
分配内存,则适用上述信息。如果您使用new
和delete
,则您正在为对象分配存储空间和构造对象,因此更改已分配块的大小没有意义——C++ 中的对象是固定大小的。
【讨论】:
【参考方案3】:如果你有n
字节的malloc
ated内存,你可以realloc
m
字节(其中m
n),从而丢弃最后的n-m
字节。
要从头扔掉,你可以malloc
一个新的、更小的缓冲区和memcpy
你想要的字节,然后free
原来的。
使用 C++ new
和 delete
也可以使用后一个选项。它还可以模拟第一个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++:释放已分配指针的一部分的主要内容,如果未能解决你的问题,请参考以下文章