我知道以下几点:
- malloc
- 卡洛克
- 重新分配
这些之间有什么区别?为什么 malloc 似乎几乎完全被使用?编译器之间是否存在行为差异?
我知道以下几点:
这些之间有什么区别?为什么 malloc 似乎几乎完全被使用?编译器之间是否存在行为差异?
malloc
分配内存。内存的内容保持原样(充满之前的任何内容)。
calloc
分配内存并将其内容设置为全零。
realloc
更改现有分配的内存块的大小,或将现有内存块的内容复制到请求大小的新分配块中,然后释放旧块。
显然,realloc
是一种特殊情况。如果您没有要调整大小(或复制和解除分配)的旧内存块,则没有理由使用它。malloc
通常使用的原因calloc
是因为将内存设置为全零会产生运行时成本,并且如果您打算立即用有用的数据填充内存(这很常见),那么归零没有意义先说出来。
这些函数都是标准的,并且在编译器中运行可靠。
除了您提到的那些(有些是扩展):
alloca
调用可以让您在堆栈帧中分配可变长度的块。shm_open
oropen
和的组合mmap
。shmget
etc 调用一种尚未提及的分配内存的方法是alloca(size_t size)
在当前堆栈帧上保留 size 个字节的内存,并在您离开堆栈帧时再次自动释放内存。
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 之后添加了一个清除。
malloc 可以(但可能永远不会)实现为:
void * malloc(size_t size) {
return realloc(NULL, size);
}
因为您可以将 realloc 一个 NULL 指针作为前一个指针传递,但 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 库用于调试和错误检测。其他人可能会提供更好的性能。有些针对同时为几个不同的线程分配内存进行了优化,避免了不同的线程需要锁定整个堆来执行分配或释放。
不过,从应用程序的角度来看,它们都应该提供相同的语义。
malloc:假设你有ptr=(int *)malloc(10); 这分配了 10 个连续字节的内存空间,第一个字节的地址存储在指针变量ptr中。分配的内存现在包含垃圾值。
所以如果 i 从 0 变化到 3 scanf("%d",ptr+i); 在 4 个连续位置存储 4 个整数。ptr具有第一个整数的地址,ptr+1具有第二个数字的地址,依此类推。因此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。