在创建数组的时候,我们必须提前指定数组大小,那就会存在开辟空间过大或者过小的问题,所以需要用到内存管理。
1、malloc
void* malloc(size_t size);
申请一片size字节大小的空间,返回一个指针,这个指针指向的是这片内存空间的起始位置,如果没有申请成功就返回NULL。
2、callocvoid* calloc(size_t num,size_t size);
开辟num个元素的空间,每个元素的大小是size字节,并且初始化为0.
如果成功返回开辟空间的起始地址,否者返回NULL
3、reallocvoid* realloc (void* ptr, size_t size);
修改ptr指向的内存空间的大小,当ptr为NULL时返回realloc的功能和malloc一样。
如果成功返回起始位置的地址,如果失败返回NULL。
在realloc重新开辟空间的过程中,有可能在原有空间上接一个空间,也有可能从新开辟一个空间。
使用realloc的时候需要注意,如果空间增容不成功会返回NULL,会把原来的空间覆盖掉,所以最好不要直接将realloc的返回值赋给原来的指针。
#include4、free#include #include #include int main() { int* str = (int*)malloc(3 * sizeof(int)); if (NULL == str)//开辟不成功 { printf("%s", strerror(errno)); return 0; } int* temp = (int*)realloc(str, 5 * sizeof(int)); if (NULL != temp) { str = temp; temp = NULL; } free(str); str = NULL; return 0; }
将开辟的空间释放掉,free后记得将指针设为NULL
5、常见错误1.对NULL指针的解引用操作
2.对动态开辟空间的越界访问
3.对非动态开辟内存使用free释放
4.使用free释放一块动态开辟内存的一部分(一般情况下不要修改返回指针所指向的位置)
5.对同一块动态内存多次释放
6.动态内存开辟的空间忘记释放(内存泄漏)
6、经典笔试题1.
#include#include #include void GetMemory(char* p) { p = (char*)malloc(100); } void test() { char* str = NULL; GetMemory(str); strcpy(str, "hello,world"); printf(str); } int main() { test(); return 0; }
1.p没有释放会造成内存泄漏
2.p是str的临时拷贝,因此对p的修改不会影响到str,所以str仍是NULL,对空指针使用strcpy函数会时程序崩溃。
如果想达到预期的效果可以传地址
#include#include #include void GetMemory(char** p) { *p = (char*)malloc(100); } void test() { char* str = NULL; GetMemory(&str); strcpy(str, "hello,world"); printf(str); free(str); } int main() { test(); return 0; }
2.
#includechar* GetMemory() { char p[] = "hello world"; return p; } void test() { char* str = NULL; str = GetMemory(); printf(str); } int main() { test(); return 0; }
在GetMemory函数中创建了字符数组p,返回的是字符数组首元素的地址,但是内存空间已经被操作系统释放了,因此通过str去访问那片空间读到的是不确定的值
3.
#include#include #include void test() { char* str = (char*)malloc(100); strcpy(str, "hello"); free(str); if (str != NULL) { strcpy(str, "world"); printf(str); } } int main() { test(); return 0; }
str已经释放了,但是没有置空,会造成非法访问
7、c/c++程序的内存开辟 8、柔性数组在c99中,结构体中的最后一个元素允许是未知大小的数组,这叫做柔性数组成员
struct s
{
int i;
int a[];
};
//或者
struct s
{
int i;
int a[0];
};
柔性数组的特点:
结构中的柔性数组成员前面必须至少一个其他成员。
sizeof返回的这种结构大小不包括柔性数组的内存
包含柔性数组成员的结构用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
#include#include struct s { int i; int a[]; }; int main() { struct s* ps = (struct s*)malloc(sizeof(struct s) + 40);//int a[10] return 0; }



