【问题标题】:Allocating memory for one dimensional array in C在C中为一维数组分配内存
【发布时间】:2014-03-28 10:20:13
【问题描述】:

我有一个关于创建动态数组的问题。

int *p; 
p = malloc( 3 * sizeof( int ) );

// initializes elements in the array
for ( int i = 0; i < 3; ++i ) {
    *p++ = i * 4;
}

如何释放我刚刚分配的内存?出于某种原因,我发现释放二维数组比一个 LOL 更容易。自从我上次使用 C 以来已经有一段时间了。

如果我执行以下操作:

free( p ); // will probably get an error. 

关于指针的另一件事。我试过这个:

int * p = malloc( sizeof( int ) );
*p = 4;

printf( "%d\n", *p ) // prints 4 as expected

free( p );
printf( "%d\n", *p ) // still prints the number 4!!!

free 函数应该释放 p 指向的内存块。那printf stills怎么打印4呢?

【问题讨论】:

  • 你可以免费使用(p);它不应该失败
  • +1 表示不转换 malloc 的返回值。
  • 我没有转换 malloc 的返回值,因为我使用的是 C99。

标签: c


【解决方案1】:

Malloc() 返回一个指向已分配块的指针。保留它以备将来使用 free()。 用整数索引你的数组或用指针遍历它,但将原始地址保存在某个地方。

你可以这样做

int *p = malloc(3 * sizeof(int));
for( int i = 0; i < 3; i++)
   p[i] = 4*i;
// .....
free(p);

int *p = malloc(3 * sizeof(int));
int *q = p;
for( int i = 0; i < 3; i++)
   *q++ = 4*i;
// .....
free(p);

【讨论】:

  • 非常感谢!我明白为什么我收到错误消息了。我会记住你说的话。
【解决方案2】:

在第一种情况下,您只需写free(p),因为您只分配了一个内存块。

您在第二种情况下所做的是未定义的行为。它可能会打印 4,它可能会崩溃,它实际上可以做任何事情。有可能实现只是将该位置标记为可重用,但实际上并没有清除它(为什么要这样做,这是浪费时间)

【讨论】:

    【解决方案3】:

    free(p) de 分配p 指向的内存。但是p 仍然有由free(p) 分配的内存地址。解除分配意味着将内存块添加到由内存分配模块维护的空闲内存列表中。当您打印 p 指向的数据时,仍然会在地址处打印值,因为该内存已添加到空闲列表中而不是删除。

    【讨论】:

      【解决方案4】:
      1. 如何释放我刚刚分配的内存?

        你可以这样做

        int *p; 
        p = malloc( 3 * sizeof( int ) );
        
        // initializes elements in the array
        for ( int i = 0; i < 3; ++i ) {
            p[i] = i * 4;
        }
        

        这不会改变p,所以你可以使用free(p) 来释放它。

        如果你需要改变p,你应该在另一个变量中记住它的原始值,然后在那个原始值上调用free(),比如

        int *op;
        op = p;
        
        /* do something that changes `p` */
        
        free(op);
        
      2. printf Stills是怎么打印4的

        您所做的,在释放后访问动态分配的内存区域,将导致未定义的行为。它可以打印4,也可以崩溃或做一些非常疯狂的事情。

      【讨论】:

        【解决方案5】:

        Malloc ==> 只分配内存(不改变内存数据为 NULL )

        Free ==> 只有它会释放指针上分配的资源,(不会将内存数据更改为 NULL )

        在这两种情况下,如果需要,用户都有责任设置适当的值。

        【讨论】:

          【解决方案6】:

          在第一种情况下,您仍然可以通过将指针返回到第一个元素的地址然后调用 free(p) 来释放内存,如下所示:

          p = p-3;
          free(p);
          

          原因:malloc 存储了一些关于一旦动态分配需要释放多少内存的信息,这就是为什么你需要将它指向开始,以便 free 可以读取该信息并准确释放 3 个 int malloc 分配的内存。

          在你的第二种情况下,它仍然打印不是通用结果,输出可以是任何东西,甚至程序可能会崩溃。

          原因:free 没有对内存做任何特别的事情,它只是将它添加回它为动态分配可用的内存维护的 FREE LIST。 仅由程序员决定在调用 free 之后是否取消对它的引用。

          【讨论】:

            【解决方案7】:

            如何释放我刚刚分配的内存?

            当我们想要释放之前由malloc() 分配的内存块时,我们使用free 函数。此函数接受指向先前分配的内存块的char 指针,并释放它 - 即,将其添加到空闲内存块列表中,可以重新分配。使用free(p)

            那么printf stills怎么打印4呢?

            Usage Of free():

            关于free()的几点说明:

            • 块的大小之前由malloc() 存储在其内存映射中,这就是free() 知道要释放多少字节的方式。
            • 未以任何方式清除或擦除已释放的内存。这就是为什么访问刚刚释放的内存通常不会导致崩溃的原因——其中的任何数据仍然与调用free()之前相同。
            • free() 函数不能使指向我们程序中可能仍然存在的给定内存块的指针无效。 在我们调用free() 之后,我们(程序员)有责任不要尝试取消引用仍然指向该内存块的指针。此类指针被称为“悬空指针”——它们指向已释放的内存,因此不应再次取消引用它们,除非为它们分配了不同(未释放)内存块的地址。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-06-21
              • 2013-02-10
              • 2012-02-05
              • 1970-01-01
              • 2015-02-01
              相关资源
              最近更新 更多