【问题标题】:Does memcpy() uses realloc()?memcpy() 是否使用 realloc()?
【发布时间】:2011-08-30 21:04:14
【问题描述】:
#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() 吗?

【问题讨论】:

    标签: c buffer memcpy realloc


    【解决方案1】:

    您的代码有未定义行为。要回答您的问题,memcpy 不使用 reallocsizeof(buf) 应该足以容纳 strlen(str)。任何不足都是崩溃。

    输出可能会因为它是一个小程序而被打印出来,但在真正的大代码中它会导致难以调试的错误。将您的代码更改为,

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

    另外,不要做*buff++,因为你会丢失内存记录(你分配的)。在malloc() 之后,一旦内存使用结束就应该执行free(buff),否则就是内存泄漏。

    【讨论】:

    • 我想使用这个缓冲区在我的真实应用程序中保存一个字符串。该字符串没有预定义的长度。它在程序运行时动态增长(附加一些其他字符串......)。我找到的解决方案是分配一些大内存(~1KB)。我想知道除此之外还有其他解决方案吗?请帮忙。谢谢。
    • @shan,那么您可以使用realloc()(但不能使用memcpy())。
    • 请不要从malloc 转换返回值,在 C 中这会隐藏令人讨厌的错误
    • @Jens,我从问题中复制了粘贴的代码。一些编译器在没有类型转换的情况下给出错误。
    • 是的,如果您收到警告,这是一个强烈的信号,表明您正在使用 C++ 编译器编译 C,或者您没有包含必要的头文件。
    【解决方案2】:

    您可能会打印出整个字符串,但这并不安全,您正在写入和读取未分配的内存。这会产生未定义的行为。

    memcpy 不进行任何内存分配。它只是读取和写入您提供的位置。它不会检查是否可以这样做,在这种情况下,如果您的程序没有崩溃,您就很幸运了。

    【讨论】:

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

    memcpy() 是如何工作的?

    因为您调用了未定义的行为。未定义的行为可能完全按照您的预期工作,并且可能会做一些完全不同的事情。它甚至可能在同一程序的不同运行之间有所不同。它还可以格式化您的硬盘并且仍然符合标准(当然这不太可能:P)

    未定义的行为意味着该行为实际上没有被定义为做任何事情。任何东西都是有效的,包括你看到的行为。请注意,如果您尝试free 该内存,您的目标平台的 C 运行时可能会抱怨。 ;)

    【讨论】:

      【解决方案4】:

      没有memcpy 不使用malloc。正如您所怀疑的,您正在注销buff 的结尾。在您的简单示例中,这没有明显的危害,但很糟糕。以下是一些在“真实”程序中可能出错的地方:

      • 您可能会在buff 之后在内存中分配的内容上乱涂乱画,从而导致稍后出现细微(或不那么细微)的错误。
      • 您可能会在 mallocfree 内部使用的标头上乱涂乱画,从而导致下次调用这些函数时出现崩溃或其他问题。
      • 您最终可能会写入一个尚未分配给您的进程的地址,在这种情况下您的程序将立即崩溃。 (我怀疑这是您所期望的。)

      malloc 实现将未映射的保护页放在分配的内存周围(通常)导致程序在这种情况下崩溃。其他实现会检测到这一点,但仅在您下次调用 mallocfree 时(或者当您调用特殊函数来检查堆时)。

      【讨论】:

        猜你喜欢
        • 2010-09-26
        • 2014-02-08
        • 2012-02-22
        • 2021-12-28
        • 2017-07-29
        • 2016-02-16
        • 2013-04-21
        • 1970-01-01
        • 2013-09-28
        相关资源
        最近更新 更多