重新分配后如何将新内存清零
调用 realloc 后将新内存清零同时保持最初分配的内存完整的最佳方法是什么?
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
size_t COLORCOUNT = 4;
typedef struct rgb_t {
int r;
int g;
int b;
} rgb_t;
rgb_t** colors;
void addColor(size_t i, int r, int g, int b) {
rgb_t* color;
if (i >= COLORCOUNT) {
// new memory wont be NULL
colors = realloc(colors, sizeof(rgb_t*) * i);
//something messy like this...
//memset(colors[COLORCOUNT-1],0 ,sizeof(rgb_t*) * (i - COLORCOUNT - 1));
// ...or just do this (EDIT)
for (j=COLORCOUNT; j<i; j++) {
colors[j] = NULL;
}
COLORCOUNT = i;
}
color = malloc(sizeof(rgb_t));
color->r = r;
color->g = g;
color->b = b;
colors[i] = color;
}
void freeColors() {
size_t i;
for (i=0; i<COLORCOUNT; i++) {
printf("%x\n", colors[i]);
// can't do this if memory isn't NULL
// if (colors[i])
// free(colors[i]);
}
}
int main() {
colors = malloc(sizeof(rgb_t*) * COLORCOUNT);
memset(colors,0,sizeof(rgb_t*) * COLORCOUNT);
addColor(0, 255, 0, 0);
addColor(3, 255, 255, 0);
addColor(7, 0, 255, 0);
freeColors();
getchar();
}
What is the best way to zero out new memory after calling realloc while keeping the initially allocated memory intact?
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
size_t COLORCOUNT = 4;
typedef struct rgb_t {
int r;
int g;
int b;
} rgb_t;
rgb_t** colors;
void addColor(size_t i, int r, int g, int b) {
rgb_t* color;
if (i >= COLORCOUNT) {
// new memory wont be NULL
colors = realloc(colors, sizeof(rgb_t*) * i);
//something messy like this...
//memset(colors[COLORCOUNT-1],0 ,sizeof(rgb_t*) * (i - COLORCOUNT - 1));
// ...or just do this (EDIT)
for (j=COLORCOUNT; j<i; j++) {
colors[j] = NULL;
}
COLORCOUNT = i;
}
color = malloc(sizeof(rgb_t));
color->r = r;
color->g = g;
color->b = b;
colors[i] = color;
}
void freeColors() {
size_t i;
for (i=0; i<COLORCOUNT; i++) {
printf("%x\n", colors[i]);
// can't do this if memory isn't NULL
// if (colors[i])
// free(colors[i]);
}
}
int main() {
colors = malloc(sizeof(rgb_t*) * COLORCOUNT);
memset(colors,0,sizeof(rgb_t*) * COLORCOUNT);
addColor(0, 255, 0, 0);
addColor(3, 255, 255, 0);
addColor(7, 0, 255, 0);
freeColors();
getchar();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
没有办法将这个问题作为一般模式来解决。原因是为了知道缓冲区的哪一部分是新的,您需要知道旧缓冲区有多长。在 C 中不可能确定这一点,因此无法找到通用解决方案。
不过你可以像这样写一个包装器
There is no way to solve this as a general pattern. The reason why is that in order to know what part of the buffer is new you need to know how long the old buffer was. It's not possible to determine this in C and hence prevents a general solution.
However you could write a wrapper like so
可能不需要执行
memset
:在使用稍后有效的内容进行设置之前,您可能不会使用colors[k]
。例如,您的代码将colors[i]
设置为新分配的color
指针,因此您不需要设置colors[i]
为NULL
。但是,即使您想“将其清零,这样一切都很好”,或者确实需要新指针为 NULL:C 标准并不保证所有位为零都是 null指针常量(即
NULL
),因此memset()
无论如何都不是正确的解决方案。您可以做的唯一可移植的事情是在循环中将每个指针设置为 NULL:
您的主要问题是您的 realloc() 调用是错误的。 realloc() 返回一个指向已调整大小的内存的指针,它不会(必然)就地调整其大小。
因此,您应该这样做:
如果您确实想知道
memset()
调用应该是什么,则需要将从colors+COLORCOUNT
开始的内存设置为零,并且将 i+1-COLORCOUNT 成员设置为零:但正如我上面所说,所有字节为零并不能保证都是 NULL 指针,因此您的 memset() 无论如何都是没用的。如果您想要 NULL 指针,则必须使用循环。
There is probably no need to do the
memset
: you may not be usingcolors[k]
before setting it with something valid later. For example, your code setscolors[i]
to a newly allocatedcolor
pointer, so you didn't need to setcolors[i]
toNULL
.But, even if you wanted to "zero it out so everything is nice", or really need the new pointers to be
NULL
: the C standard doesn't guarantee that all-bits-zero is the null pointer constant (i.e.,NULL
), somemset()
isn't the right solution anyway.The only portable thing you can do is to set each pointer to
NULL
in a loop:Your primary problem is that your
realloc()
call is wrong.realloc()
returns a pointer to the resized memory, it doesn't (necessarily) resize it in-place.So, you should do:
If you really want to know what the
memset()
call should be, you need to set to zero the memory starting atcolors+COLORCOUNT
, and seti+1-COLORCOUNT
members to zero:But as I said above, all bytes zero is not guaranteed to be a
NULL
pointer, so yourmemset()
is useless anyway. You have to use a loop if you wantNULL
pointers.首先,realloc 可能会失败,因此您需要检查 NULL。其次,没有更好的方法将内存清零:只需从旧缓冲区的末尾到较大缓冲区的末尾进行 memset 即可。
First of all, realloc can fail, so you need to check for NULL. Second, there is no better way to zero out the memory: just memset from the end of the old buffer to the end of the larger buffer.
编写您自己的函数,例如
reallocz
,它接受当前大小作为参数,并为您调用realloc
和memset
。它真的不会比你已经拥有的更好......毕竟它是 C。Write your own function, say
reallocz
, that accepts the current size as a parameter, and callsrealloc
andmemset
for you. It really won't get much better than what you already have... it's C, after all.在 Linux 上,现在有
size_t malloc_usable_size (void *ptr)
,由
提供。可以在 https://linux.die.net/man/3/malloc_usable_size。这意味着您现在可以为
realloc(3)
编写通用包装器:请注意,
malloc_usable_pointer(3)
不一定返回与您调用calloc(3)
时使用的字节数相同 - 例如,在我的 Linux 计算机上打印
16
。另请注意,您应该仅在通过
calloc(3)
获得的堆分配上调用上述realloc_zero()
,因为calloc()
将对malloc_usable_pointer()
报告的任何额外字节进行零初始化。On Linux, there is now
size_t malloc_usable_size (void *ptr)
, provided by<malloc.h>
. Find the man page at https://linux.die.net/man/3/malloc_usable_size.This means you now can write a general-purpose wrapper for
realloc(3)
:Note that
malloc_usable_pointer(3)
doesn't necessarily return the same number of bytes that you calledcalloc(3)
with -- for example,prints
16
on my Linux machine.Also note that you should only call the above
realloc_zero()
on heap allocations obtained throughcalloc(3)
, sincecalloc()
will zero-initialize any extra bytes reported bymalloc_usable_pointer()
.