memcpy()函数是否使用realloc()函数?

7
#inlcude <stdio.h>
#inlcude <stdlib.h>
#inlcude <string.h>

int main() {
    char *buff = (char*)malloc(sizeof(char) * 5);
    char *str = "abcdefghijklmnopqrstuvwxyz";

    memcpy (buff, str, strlen(str));

    while(*buff) {
        printf("%c" , *buff++);
    }

    printf("\n");

    return 0;
}

这段代码打印了完整的字符串“abc...xyz”。但是“buff”没有足够的内存来容纳该字符串。memcpy()函数是如何工作的?它使用realloc()函数吗?

4个回答

13

你的代码存在未定义行为。回答你的问题,不会memcpy 不使用 realloc

sizeof(buf) 应该足以容纳 strlen(str)。任何小于此的值都会导致崩溃。

尽管输出结果可能是正确的,因为这是一个小程序,但在真正的大型代码中,它会导致难以调试的错误。请将您的代码修改为以下形式:

const char* const str = "abcdefghijklmnopqrstuvwxyz";
char* const buff = (char*)malloc(strlen(str) + 1);

另外,不要使用 *buff++,因为这会导致内存记录(即你所分配的内存)丢失。在使用 malloc() 分配内存后,应该在使用完毕后调用 free(buff),否则就会出现内存泄漏。


我想在我的实际应用程序中使用这个缓冲区来保存一个字符串。该字符串没有预定义的长度,它会在程序运行时动态增长(附加其他字符串...)。我找到的解决方案是分配一些大内存(~1KB)。我想知道除此之外是否有其他不同的解决方案?请帮忙。谢谢。 - shan
@shan,你可以使用realloc()(但不是memcpy())来实现此目的。 - iammilind
请不要在C语言中对malloc的返回值进行强制类型转换,这样可能会掩盖一些严重的错误。 - Jens Gustedt
@Jens,我已经从问题中复制粘贴了代码。一些编译器在没有进行类型转换的情况下会出现错误。 - iammilind
@iammilind:C++ 编译器会发出警告,但符合标准的 C 编译器 必须 不发出。 - jamesdlin
1
是的,如果你在这方面收到了警告,那么这是一个强烈的信号,说明有些地方出了问题,可能是你正在使用C++编译器编译C代码,或者你没有包含必要的头文件。 - Jens Gustedt

9
你可能会打印出整个字符串,但这是不安全的,你正在读写未分配的内存。这会产生未定义行为。 memcpy 不进行任何内存分配。它只是从你提供的位置读取和写入。它不检查是否可以这样做,在这种情况下,如果你的程序没有崩溃,那么你很幸运。

谢谢你的回答。但是,如果我不知道字符串的长度,我该如何分配足够的内存?我想要创建一个缓冲区。我想要避免写入和读取未分配的内存。我需要在我的代码中做哪些更改?请帮忙,谢谢。 - shan
@shan - 如果您正在调用 "memcpy",并且您知道要复制多少内存,则知道需要分配多少内存。使用 strlen 查找字符串的长度(它查找终止空字符)。 - sje397
是的,您可以使用 strlen,就像您为 memcpy 所做的那样,除了一个细节。strlen 函数不计算字符串末尾的空字符。因此,在 mallocmemcpy 中,您需要使用 strlen(str)+1。此外,在 malloc 中,您不需要乘以 sizeof(char)。根据定义,sizeof(char) == 1 - andrewdski
我想在我的实际应用程序中使用这个缓冲区来保存一个字符串。该字符串没有预定义的长度。它会在程序运行时动态增长(附加其他字符串...)。我找到的解决方案是分配一些大内存(~1KB)。我想知道除此之外是否有其他不同的解决方案?请帮忙,谢谢。 - shan
@shan - 在这种情况下,通常人们会分配一个大的字符串缓冲区,但如果潜在长度可能更大,您应该使用realloc根据需要扩展您的缓冲区。 - sje397

1
memcpy()是如何工作的?
因为您已经调用了未定义的行为。未定义的行为可能会按照您的期望正常工作,也可能完全不同。它甚至可能在同一程序的不同运行之间有所不同。它甚至可以格式化您的硬盘,并且仍然符合标准(当然这是不太可能的:P)
未定义的行为意味着行为实际上没有被定义为做任何事情。任何行为都是有效的,包括您正在看到的行为。请注意,如果您尝试释放该内存,则目标平台的C运行时可能会抱怨。;)

1

memcpy 没有使用 malloc。正如你所怀疑的那样,你正在越过 buff 的末尾进行写入。在你的简单示例中,这似乎没有什么影响,但是这是不好的。下面是在“真实”程序中可能出现的一些问题:

  • 你可能会涂抹到跟随你的 buff 分配的内存中,导致后续出现微妙(或不太微妙)的错误。
  • 你可能会涂抹到被 mallocfree 内部使用的标头上,导致在下一次调用这些函数时发生崩溃或其他问题。
  • 你可能会写入一个未分配给你的进程的地址,此时你的程序将立即崩溃。(我猜这就是你预期的情况。)

有些 malloc 实现会在分配的内存周围设置未映射的警戒页面,以便在这种情况下(通常)导致程序崩溃。其他实现将检测到此情况,但仅在下一次调用 mallocfree 时(或当你调用检查堆的特殊函数时)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接