在C中分配内存的所有方法是什么?它们有何不同?

时间:2010-09-24 21:55:11

标签: c dynamic-memory-allocation

我知道以下内容:

  • 的malloc
  • 释放calloc
  • 的realloc

这些之间有什么区别?为什么malloc似乎几乎完全被使用?编译器之间是否存在行为差异?

5 个答案:

答案 0 :(得分:12)

malloc分配内存。记忆的内容保持原样(用之前的任何东西填充)。

calloc分配内存并将其内容设置为全零。

realloc更改现有已分配内存块的大小,或将现有内存块的内容复制到新分配的请求大小的块中,然后释放旧块。

显然,realloc是一种特殊情况。如果您没有旧的内存块来调整大小(或复制和取消分配),则没有理由使用它。通常使用malloc而不是calloc的原因是因为将内存设置为全零存在运行时成本,并且如果您计划立即使用有用数据填充内存(通常情况下,首先将其归零是没有意义的。

这些函数都是标准函数,并且在编译器之间可靠地运行。

答案 1 :(得分:3)

除了你提到的那些(有些是扩展名):

  • 堆栈上的变量也是动态分配的。递归是一种分配和使用它的方法。
  • C99有可变长度数组(如BlueRaja所述)。
  • 在某些系统上,您甚至可以进行alloca调用,以便在堆栈框架中分配可变长度的块。
  • POSIX具有内存段和文件的映射,包含shm_openopenmmap的组合。
  • SysV IPC有shmget等电话

答案 2 :(得分:2)

分配未提及的内存的一种方法是alloca(size_t size),它在当前堆栈帧上保留大小字节的内存,并在离开堆栈帧时自动再次释放内存。

答案 3 :(得分:1)

calloc可能只是实现类似于:

void * calloc(size_t nmemb, size_t size) {
      size_t len = nmemb * size);
      void * ptr = malloc(len);
      if (ptr) {
          return memset(ptr, 0, len);
      }
      return ptr;
}

所以它只是在malloc之后添加了一个乘法和一个明确的。

malloc可以(但可能永远不会)实现为:

void * malloc(size_t size) {
      return realloc(NULL, size);
}

因为您可以将一个NULL指针作为前一个指针传递realloc,但malloc很可能没有像那样实现,因为它会减慢所有malloc并且因为realloc可能使用malloc。

关于realloc的主要知识是它通常能够确定任何堆分配例程返回的内存块的实际大小,并查看块是否已经足够大,或者在某些情况下是否会最好尽量缩小块或移动它。

void realloc(void * ptr, size_t size) {
    size_t alen = MALLOC_LENGTH_OF(ptr); // this just stands for some method of determining
                                     // the size of the block that was allocated, and could
                                     // be looking it up in a table or looking at a place
                                     // several bytes before the pointer, or some other
                                     // implementation specific thing
    if (0 == size) {
       free(ptr);
       return NULL;
    }
    if (alen >= size) {
        return ptr; // big enough, and not worrying about it being too big
    }
    void new_ptr = malloc(size); // since I said that malloc most likely isn't
                                // implemented using realloc using malloc here is ok
    if (new_ptr && ptr) {
       memcpy(new_ptr, ptr, alen);
    }
    free(ptr);
    return new_ptr;
}

Malloc的使用更多,因为它最简单。程序员通常可以使他们的分配足够大,开始时他们不必担心使用realloc调整它们的大小,并且通常不需要清理内存。

不同的库之间存在不同的行为,您甚至可以将程序与其他版本链接,以便在没有(通常不更改编译器)的情况下获得这种不同的行为。

某些malloc库用于调试和错误检测。其他人可能提供更好的表现有些针对几个不同线程同时分配内存进行了优化,避免了需要锁定整个堆来执行分配或释放的不同线程。

但是,所有这些应该从应用程序的角度提供相同的语义。

答案 4 :(得分:0)

malloc:假设你有 ptr =(int *)malloc(10); 这会分配10个连续字节的内存空间,第一个字节的地址是存储在指针变量 ptr 中。分配的内存现在包含垃圾值 因此,如果i从0变为3 scanf(“%d”,ptr + i); 在4个连续位置存储4个整数。 ptr 的地址为第1个整数, ptr + 1 的地址为第2个数字,依此类推。 因此 printf(“%d”,atstrick(ptr + i)); 将打印相应的值。 与为变量和数组分配的内存不同,动态分配没有与之关联的名称。如上所示。

calloc:除了两个不同之外,它类似于malloc: 1. 声明: ptr =(int *)calloc(5,sizeof(int));这里我们有两个参数,5是没有分配的块,第二个参数等于4个字节。这相当于 ptr =(int *)malloc(5 * sizeof(int)); 2。在calloc内存中,最初分配的不是垃圾,但它是0.如果堆中没有足够的可用内存,malloc和calloc都返回NULL。