假设我有一个char指针指向内存中的某个字符串 并假设我想将该字符串复制到内存中的其他位置。
void cpy(char **dst, char *src)
{
*dst = (char *) realloc(*dst, strlen(src) + 1);
memcpy(*dst, src, strlen(src) + 1);
}
(假设内存分配成功,src
不为NULL)
如果我这样称呼这个函数怎么办:
char *str = malloc(14);
memcpy(str,"hello, world!", 14);
cpy(&str,str+7);
现在我希望srt
指向字符串"world!"
(在我的测试中它会发生)。
但令我担忧的是,在cpy
的来电中,*dst
和src
实际指向相同字符串的不同位置。并且,在realloc
上调用*dst
时,可能会释放此内存。但在接下来的一行中,我试图用memcpy
从那个地方复制。
所以问题是:它有什么问题吗? 或者用另一种方式 - 是否可以释放记忆,然后立即使用它?
感谢。
注意:示例已更新,以便在使用realloc
获取的内存上调用malloc
。
答案 0 :(得分:9)
这一切都有问题。在realloc
等未获得的指针上调用malloc
是彻头彻尾的未定义行为。
正如@Daniel Fischer指出的那样,在重叠的内存区域使用memcpy
也是未定义的行为(在这种情况下你应该使用memmove
),所以你必须小心。
更新:经过实质性修改后,问题就完全不同了。它现在相当于这个压缩版本:
char * s = malloc(14);
strcpy(s, "hello, world!");
char * p = realloc(s, 14);
memcpy(p, s, 14);
这也是未定义的行为,因为在成功s
之后不允许再访问realloc
指向的内存,并且不允许您访问p
指向的内存。 {1}} realloc
失败后的{1}}。
答案 1 :(得分:1)
您的示例中的隐含假设是允许cpy
释放它未分配的内存。这是一种狡猾的假设,但只要它是有意的,那就没关系。在这种情况下,请分别使用malloc
和free
而不是realloc
:
void cpy(char **dst, char *src)
{
// obtain completely new memory (realloc might do this anyway)
char* new = malloc(strlen(src) + 1);
// duplicate the string
memcpy(new, src, strlen(src) + 1);
// release the original memory now that we know we are done with it
free(*dst);
// indicate where to find the new string
*dst = new;
}
这仍然不是一个好主意,因为没有办法知道其他变量可能指向你free
的内存,但是如果你有办法做出这样的保证,这个是你需要的代码类型。