【问题标题】:Confusion in malloc() in C, Dynamic Memory Allocation [duplicate]C中的malloc()混淆,动态内存分配[重复]
【发布时间】:2017-08-17 10:36:38
【问题描述】:
int* ptr;
ptr=(int*)malloc(sizeof(int)); //(A)
ptr=(int*)malloc(5*sizeof(int)); //(B)

在 (A) 行,将动态创建一个 4 字节的块。现在这很好。但我的问题是在 B 行,它会创建一个 20(5*4) 字节块吗?还是 5 个大小为 4 字节的单独块?如果它创建一个单独的块,那么它们会是连续的吗? ptr=(int*)malloc(5*sizeof(int)); and ptr=(int*)calloc(5,sizeof(int)); 是否等效?

【问题讨论】:

  • 创建一个这样的函数:void foo(int x) { printf("%d\n", x); },现在调用它:foo(5*sizeof(int));。它打印20 还是打印5*sizeof(int)?为什么?这些信息足以让您自己回答这个问题吗? malloc 怎么知道8*sizeof(int8_t)4*sizeof(int16_t)2*sizeof(int32_t)1*sizeof(int64_t) 之间的区别?
  • 不要强制返回 malloc。

标签: c


【解决方案1】:

它们实际上是等价的。 malloc 将分配连续块。 区别在于calloc 对内存进行零初始化,而malloc 没有。

当然,我们谈论的是虚拟内存。该块对于您的程序将是连续的。它可以不在物理内存中。但在大多数情况下,这并不重要,除非你不尝试做内核模块或驱动程序,它们在环 0 中工作。但情况不同。

【讨论】:

  • 我添加了关于虚拟内存和物理内存区别的注释。虚拟内存必须是连续的,因为malloc不理解,你是传(sizeof(int) * 4)还是sizeof(MyMegaStructure)
【解决方案2】:

但我的问题是在 B 行,它会创建一个 20(5*4) 字节块吗?

ptr = malloc(5*sizeof(int)) 将分配5*sizeof(int) 字节的空间。是的,分配的空间将是连续的,如果连续空间不可用,则分配将失败。

ptr=(int*)malloc(5*sizeof(int));ptr=(int*)calloc(5,sizeof(int)); 是否等效?

它们是等价的,只是calloc 将分配的内存设置为0


注意:在 C 中,您不应强制转换 malloccallocrealloc 的返回值。

【讨论】:

  • 我没有DV,但我猜它是由“它们可能是连续的,也可能不是连续的”引起的。这取决于我们是否在谈论虚拟/物理内存。
  • @FilipKočica;这可能是原因。现在我让它变得简单了。
【解决方案3】:

malloc() 尝试分配您要求的内存大小。该函数不知道参数是如何传递的,而只知道它的值。

例如,如果 sizeof(int) 为 4,则:

int* ptr = malloc(sizeof(int) * 5);

int* ptr = malloc(20);

本质上是一样的。在这两个函数中,都会得到一个值 20 作为参数。如果你像这样调用 malloc 也会发生同样的情况:

size_t a = 20;
int* ptr = malloc(a);

因此,如果它成功(即不返回 NULL),它将分配一个连续的内存块,至少具有您要求的大小。

所有关于虚拟内存的说法都是正确的。这意味着,您将使用连续索引访问内存。物理内存取决于操作系统管理您的内存的方式。

例如,如果您的操作系统仅保存 4kb 大小的内存页框(物理内存块),并且您在 malloc 中要求更多,尽管您的虚拟内存将是连续的,但物理内存可能不会。

所有这些都与更广泛的主题有关,即内存管理。您可以阅读 linux 选择处理它的方式here

【讨论】:

    【解决方案4】:

    Malloc 获取要分配的块的请求大小,以字节表示。它不能(也不能,真的)确定你如何得到一个给定的数字,即大小是5*sizeof(int),就像你的例子一样,还是2030-10。无论哪种情况,它都会分配一个 20 字节的块(假设 int 的大小为 4 字节)。

    【讨论】:

      【解决方案5】:
      1. 是的。 malloc 将分配连续块,或者如果没有足够大的连续块可用,malloc 将失败。 (malloc 失败将返回一个 NULL 指针。)

      2. Malloc 和 Calloc 都分配内存,但 calloc 初始化为零,而 malloc 没有。

      【讨论】:

        【解决方案6】:

        首先是bad to castmalloc()的返回值。此函数将您要分配的字节数作为输入。无论您传递(5*sizeof(int)) 还是20 都没有关系(假设您的机器上的int4 字节)。将分配具有给定字节数的块。当我说块时,我的意思是你可以像这样访问每个字节:

        char *ptr = malloc(5*sizeof(int));
        ptr++;  // now ptr points to the second byte of the chunk.
        

        或者,你可以这样做:

        int *ptr = malloc(5*sizeof(int));
        ptr++;  // now ptr points to the second element (that's sizeof (int) bytes away) from the start of the chunk.
        

        是 ptr=(int*)malloc(5*sizeof(int));和 ptr=(int*)calloc(5,sizeof(int));等价的?

        当使用malloc 时,你不应该假设任何关于内存块的内容。当您使用calloc 时,块中的所有字节都保证设置为0malloc 可能在某些实现上比 calloc 快。除此之外没有区别。

        【讨论】:

        • 除了“强制转换 malloc() 的返回值”之外,还应该做什么
        • @AndreasH: "what else": 什么都没有(在 C 中)。
        猜你喜欢
        • 2013-06-09
        • 2012-12-13
        • 2022-11-10
        • 2020-11-01
        • 2013-10-13
        • 2018-10-16
        • 1970-01-01
        • 2021-09-20
        • 1970-01-01
        相关资源
        最近更新 更多