【问题标题】:malloc function memory managementmalloc 函数内存管理
【发布时间】:2019-10-19 23:31:55
【问题描述】:

malloc() 函数形成一个内存块(比如 20 字节类型转换为 int),那么它如何像 calloc() 函数一样用作 int 块的数组?它不应该用于在整个 20 字节(20*8 位)中仅存储一个 int 值吗?

【问题讨论】:

    标签: c malloc dynamic-memory-allocation


    【解决方案1】:

    (比如 20 个字节类型转换为 int)

    不,返回的内存是一个指向 void 的指针,这是一个不完整的类型。

    我们将返回的指针分配给某个类型的指针变量,我们可以使用该变量来访问内存。

    引用C11,第 §7.22.3 章,内存管理功能

    [....] 如果分配成功则返回的指针经过适当对齐,以便可以分配给 指向具有基本对齐要求的任何类型对象的指针,然后使用 访问分配的空间中的此类对象或此类对象的数组(直到空间 被显式释放)。 [...] 返回的指针指向 分配的空间。 [....]

    由于分配的内存是连续的,指针算术可以工作,就像在数组的情况下一样,因为在数组中,元素也被放置在连续的内存中。

    澄清一点,a pointer is not an array.

    【讨论】:

    • 就像在 16 位架构中我们使用 2 字节(16 位)以 0 和 1 的形式表示整数值,而在 32 位架构中我们使用 4 字节(32 位)来表示相同的整数价值。这意味着一块 int 类型的任何内存都只包含一个 int。这不应该也适用于 malloc,因为它是一大块内存。
    • @VIbhor 是的,如果您分配的内存价值为 sizeof 一个 int,您将获得 2 个字节或 4 个字节,具体取决于您的环境。但是,如果您要求 20 字节,malloc 将返回 20 字节的内存,它不知道该内存的未来使用情况。
    • @VIbhor 您是否会在这里混淆位和字节?
    • @VIbhor 这不是一个单一的int 变量,它是一个多个 int 变量的块。
    • @VIbhor one single int variable block- 不,不是那样的。正如我之前提到的,malloc 返回的内存不是基于任何类型的,它只是一个内存,具有定义的大小,适合对齐以分配给任何其他类型的指针 - 就是这样。
    【解决方案2】:

    C 中有一个抽象概念,正式称为有效类型,表示存储在内存中的数据的实际类型。这是编译器在内部跟踪的内容。

    C 中的大多数对象在声明变量时都有这样的有效类型,例如,如果我们输入 int a;,那么存储在 a 中的有效类型就是 int

    意味着做这样的坏事是合法的:

    int a;
    double* d = (double*)&a;
    *(int*)d = 1;
    

    这是可行的,因为实际内存的有效类型仍然是int,即使我们用一个非常不兼容的类型指向它。只要我们使用与有效类型相同的类型来访问它,一切都很好。如果我们使用错误的类型访问数据,就会发生非常糟糕的事情,例如程序崩溃或休眠错误。

    但是当我们调用malloc 系列函数时,我们只告诉他们保留n 字节数,没有指定类型。该内存保证分配在相邻的内存单元中,但仅此而已。 malloccalloc 之间的唯一区别是后者将这个原始内存中的所有值设置为零。两个函数都不知道类型或数组。

    返回的原始内存块没有有效类型。直到我们访问它的时候,它才会获得与访问所使用的类型相对应的有效类型。

    就像前面的例子一样,我们设置哪种类型的指针指向数据并不重要。我们写int* i = malloc(n);bananas_t* b = malloc(n); 都没有关系,因为指向的内存还没有类型。直到我们第一次访问它时它才会得到一个。

    【讨论】:

    • 作为malloccalloc 之间的区别,calloc 实现倾向于检查溢出。此外,根据§6.3.2.3 ¶7,您的示例可能会导致 UB。否则,一个很好的答案。
    • @ninjalj §7 中的 UB 非常理论化。没有具有不同对齐要求的指针的系统。不同的指针大小,当然,但是当转换为更大的指针类型时,指针会错位?我相当肯定这样的系统从未存在过,也永远不会存在。我什至不知道为什么这部分在标准中。
    【解决方案3】:

    malloc返回的内存与从calloc返回的内存相比没有什么特别之处,除了calloc返回的内存块的字节被初始化为0。malloc返回的内存不必用于单个对象,也可以用于数组。

    这意味着以下是等价的:

     int *p1 = malloc(3 * sizeof(int));
     p1[0] = 1;
     p1[2] = 2;
     p1[3] = 3;
     ...
     int *p2 = calloc(3, sizeof(int));
     p2[0] = 1;
     p2[2] = 2;
     p2[3] = 3;
    

    两者都将返回 3 * sizeof(int) 字节的内存,可用作大小为 3 的 int 数组。

    【讨论】:

      【解决方案4】:

      malloc 返回给您的只是一个指向分配连续内存块的起始内存地址的指针。

      您使用 malloc 分配的连续内存块的大小取决于您传递给 malloc 函数的参数。 http://www.cplusplus.com/reference/cstdlib/malloc/

      如果您想存储int 变量,那么您可以通过将您使用的指针类型定义为int 类型来实现。

      示例:

      int p*; //pointer of type integer
      size_t size = 20;
      p = (int *) malloc(size); //returns to pointer p the memory address
      

      在此之后,程序员可以使用指针 p 访问 int(4 字节精度)值。

      callocmalloc 的唯一区别是 calloc 将此内存块中的所有值初始化为零。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-02-09
        • 2021-11-18
        • 1970-01-01
        • 2013-06-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-03
        相关资源
        最近更新 更多