1

假设我有一个指向内存中某个字符串的 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实际上指向同一字符串的不同位置。而且,当调用时,这块内存可能会被释放。但在下一行中,我试图从那个地方复制. *dstsrcrealloc*dstmemcpy

所以问题是:它有什么问题吗?
或者换一种说法 - 释放内存并在之后立即使用它可以吗?

谢谢。

注意:该示例已更新,以便realloc在使用malloc.

4

2 回答 2

9

这一切都错了。调用不是通过etc获得的指针是完全未定义的行为。reallocmalloc

正如@Daniel Fischer 指出的那样,memcpy在重叠的内存区域上使用它也是未定义的行为(在这种情况下你应该使用memmove),所以你必须小心。


更新:在您进行大量编辑后,问题完全不同。它现在相当于这个压缩版本:

char * s = malloc(14);
strcpy(s, "hello, world!");

char * p = realloc(s, 14);

memcpy(p, s, 14);

这也是未定义的行为,因为s在成功后不允许您再访问指向的内存,并且在不成功后realloc不允许您访问指向的内存。prealloc

于 2012-11-20T21:23:35.743 回答
1

您的示例中的隐含假设是允许cpy释放未分配的内存。这是一种狡猾的假设,但只要是故意的,就可以了。单独使用mallocandfree而不是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,但是如果您有办法做出这种保证,那么这就是您需要的那种代码。

于 2012-11-20T21:40:44.467 回答