目录
1、malloc 函数:
void* malloc(size_t size);
它接收一个参数:
size
:需要分配的内存块大小(以byte
为单位)。函数会在堆上分配一块连续的内存空间,其大小为指定的
size
,并返回该内存块的起始地址。使用
malloc()
函数时需要注意以下几点:如果分配成功,函数会返回指向分配得到的内存空间的指针。如果分配失败,函数会返回
NULL
。分配得到的内存是未初始化的,其内容是不可预测的。
在使用完
malloc()
函数分配的内存后,应当使用free()
函数显式地释放内存,以避免内存泄漏。
malloc()
函数通常用于动态分配数组、结构体等可变大小的内存空间。需要注意的是,使用
malloc()
函数分配内存后,应确保在使用过程中不会超出分配的内存空间,以防止内存越界错误。此外,分配的内存空间一般不能被自动释放,需要手动使用free()
函数进行释放,避免内存泄漏。为了避免内存分配失败的情况,应当使用
if (ptr == NULL)
来判断指针是否为NULL
,以确保内存分配成功后再进行后续的操作。
2、free 函数:
void free(void* ptr);
它接收一个参数:
ptr
:指向需要释放的内存空间的指针。函数会释放指向的内存空间,并将其标记为未被使用。在释放内存后,尽管原内存指针
ptr
所指向的内存空间已被释放,但其存储的值仍可能存在,因此需要注意在使用free()
函数释放内存后,不应再使用该指针或指向该指针的指针(双重释放会导致未定义行为)。使用
free()
函数时需要注意以下几点:在使用
malloc()
、calloc()
、realloc()
函数动态分配内存后,应当使用free()
函数显式地释放内存,以避免内存泄漏。释放已经被释放的内存空间是非法的行为,也称之为“二次释放”,可能会导致程序发生不可预见的异常或崩溃。
如果在释放内存之前对已经被释放的内存进行了访问,也可能会导致程序发生异常或崩溃。
由于动态内存分配通常用于实现复杂的数据结构或者动态存储等,错误使用
free()
函数会导致程序崩溃或出现不可预见的运行时错误,因此在使用free()
函数时需要格外谨慎。
3、calloc 函数:
void* calloc(size_t nmemb, size_t size);
它接收两个参数:
nmemb
:需要分配的元素个数。size
:每个元素的大小(以byte
为单位)。函数会分配一块连续的内存空间,其大小为
nmemb * size
,并将这块内存空间的所有字节都设置为零。使用
calloc()
函数时需要注意以下几点:如果分配成功,函数会返回指向分配得到的内存空间的指针。如果分配失败,函数会返回
NULL
。分配的内存中的每个字节都被设置为零。
在使用完
calloc()
函数分配的内存后,应当使用free()
函数显式地释放内存,以避免内存泄漏。
calloc()
函数通常在需要分配数组或结构体等的内存空间,并需要对其进行初始化时使用。需要特别注意的是,由于
calloc()
在分配内存时会将其值初始化为零,因此在需要分配大块内存时可能会比malloc()
函数略微慢一些。如果仅需分配内存而不需要初始化,通常使用malloc()
函数更合适。
4、realloc 函数:
void* realloc(void* ptr, size_t size);
它接收两个参数:
ptr
:指向当前内存块的指针,如果传入NULL
,则会表现得和malloc()
函数一样。size
:需要重新分配的内存块大小(以byte
为单位)。函数会重新分配内存块,返回新的指针。如果分配失败,则会返回
NULL
,原始指针ptr
不会被释放,内存块大小也不会被改变。需要注意的是,当使用
realloc()
函数时,如果能够在原内存块的基础上扩展,则会在原内存块末尾分配新内存,否则必须分配一块新的内存,将原内存块的数据进行拷贝。使用
realloc()
函数应该注意以下几点:可以使用
if (ptr == NULL)
来判断分配的指针是否为空,以此来判断是否需要重新申请空间。如果分配失败,则会返回
NULL
,如果NULL
被传递到函数中,则可能会导致崩溃。如果分配成功,但空间大小不足,调用该函数会导致原来的指针指向一个新的地址,原来内存里的数据将会被拷贝到新地址,这会导致额外的开销,应该尽量避免使用过多的调用。
如果向
realloc()
函数传入的指针在以前使用过free()
函数释放,则使用该指针会导致不可预料的行为,应该避免这种情况。