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

问题描述 投票:0回答:7

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

c++ c memory-management
7个回答
12
投票

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

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

char * foo = malloc(4096);

foo = realloc(foo, 4096-1024);

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

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


5
投票

如果您有

n
字节的
malloc
内存,您可以
realloc
m
字节(其中
m
<
n
),从而丢弃最后的
n-m
字节。

要从头开始删除,您可以

malloc
一个新的、更小的缓冲区和
memcpy
所需的字节,然后
free
原始的。

后一个选项也可以使用 C++

new
delete
来实现。它还可以模拟第一个
realloc
案例。


5
投票

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

如果您的块分配有

malloc()
,则
realloc()
将允许您减少或增加块的大小。不过,块的起始地址不一定保持不变。

您无法更改

malloc
d内存块的起始地址,这确实是您的第二个场景所要求的。也没有办法分割一个
malloc
'd 块。

这是

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

现在,

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

对于 C++,如果您使用

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


1
投票

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


1
投票

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

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


1
投票

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

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


0
投票

未绑定到文件时 mmap(带

MAP_ANONYMOUS
)创建内存分配,允许使用 mremap(带/不带
MREMAP_MAYMOVE
)控制截断和扩展。

MAP_ANONYMOUS
mmap
实现可能在内部仅转发到
malloc
/
free
,但 realloc() 不保证截断不会被移动。由于除非提供
mremap
,否则
MREMAP_MAYMOVE
不会移动,因此可用于不可移动的截断。

MREMAP_MAYMOVE:如果指定了此标志,则允许内核在必要时将映射重新定位到新的虚拟地址。

虽然 msvc 不提供 mmap,但使用 Win32 API 也可以实现同样的功能。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.