目录
一、C语言底层内存知识补充
- 栈区:栈区主要存放函数运行中分配的局部变量、函数参数、返回数据、返回地址等。
- 堆区:⼀般由程序员分配释放(比如本讲的动态内存管理), 若程序员不释放,程序结束时可能由操作系统回收。
- 静态区:存放全局变量、静态数据。程序结束后由系统释放。
- 代码段:存放函数体的⼆进制代码。
二、动态内存函数
- 须包含头文件 <stdlib.h>
- 详见C语言官方解释:<cstdlib> (stdlib.h) - C++ Reference (cplusplus.com)
1.1free
void free (void* ptr);
- 功能:⽤来做动态内存的释放和回收。
- 注意事项:
1.如果参数 ptr 指向的空间不是动态开辟的,那free函数使用错误。
2.如果参数 ptr 是NULL,则函数无效。- 代码示例:会在其他函数示例时使用
1.2malloc
void* malloc (size_t size)
- 功能:向内存申请⼀块连续可⽤的空间
- 返回值:若开辟成功-返回所开辟空间的指针;若开辟失败-返回NULL
- 注意事项:函数返回值为void*意味着不能直接进行解引用等操作。建议使用前进行强制类型转换
- 示例代码:
int main() { int* p = (int*)malloc(20); //确保空间开辟成功后使用 if (p == NULL) { perror("malloc"); return 1; } //使用空间 for (int i = 0; i < 5; i++) { *(p + i) = i + 1; } //释放内存 free(p); p = NULL; }
1.3calloc
void* calloc (size_t num, size_t size);
- 功能:为 num 个⼤⼩为 size 的元素开辟⼀块空间,并把空间的每个字节初始化为0。
- 返回值: 若开辟成功-返回所开辟空间的指针;若开辟失败-返回NULL
- 注意事项:函数返回值为void*意味着不能直接进行解引用等操作。建议使用前进行强制类型转换
- 代码示例
int main() { int* p = (int*)calloc(5, sizeof(int)); if (p == NULL) { perror("calloc"); return 1; } //使用空间 for (int i = 0; i < 5; i++) { printf("%d", *(p + i)); } //释放内存 free(p); p = NULL; }
1.4realloc
void* realloc (void* ptr, size_t size);
- 功能:用来调整动态开辟内存的大小。
- 返回值:若成功-调整之后的内存空间首地址;若失败-返回NULL
- 细节解释:
1.若原有空间之后有⾜够⼤的空间:直接在原有内存之后扩展空间,原来空间的数据不发⽣变化。函数返回传入的原地址即可。
2.若原有空间之后没有⾜够⼤的空间:在堆空间上另找⼀个合适⼤⼩ 的连续空间来使⽤。函数返回⼀个新的内存地址。- 代码示例:
int main() { int* ptr = (int*)realloc(p, 40); if (ptr != NULL) { p = ptr; //使用空间 for (int i = 5; i < 10; i++) { *(p + i) = i + 1; } } else { perror("realloc"); return 1; } //释放空间 free(p); p = NULL; }
三、使用常见错误
3.1对非动态开辟内存使用free释放
int main()
{
int a = 10;
int *p = &a;
free(p);
}
3.2空指针未判断造成的错误
int main()
{
int *p = (int *)malloc(INT_MAX/4);
*p = 20;
free(p);
}
应该效仿前文的代码,加上对空指针的判断
3.3使用free释放一块动态开辟内存的一部分
int main()
{
int *ptr = (int *)malloc(100);
ptr++;
free(ptr); //ptr不再指向动态内存的起始位置
}
3.4对同一块动态内存多次释放
int main()
{
int *ptr = (int *)malloc(50);
free(ptr);
free(ptr); //重复释放
}
3.5动态开辟内存没有释放而造成内存泄露
动态开辟内存后必须用free释放,定义的指针必须置为空指针
3.6已开辟空间的越界访问
int main()
{
int i = 0;
int *p = (int *)malloc(10*sizeof(int));
if(NULL == p)
{
exit(EXIT_FAILURE);
}
for(i=0; i<=10; i++)
{
*(p+i) = i;
}
free(p);
}
四、典型习题练习
- 调用函数后返回的指针指向的空间被系统销毁,无法接收到数据。
char *test(void) { char p[] = "hello world"; return p; } void Test(void) { char *ptr = NULL; ptr = test(); printf(ptr); }
- free函数不会将指针置为空指针,只会将开辟的空间还给操作系统
int main { char *str = (char *) malloc(100); strcpy(str, "hello"); free(str); if(str != NULL) //str不为空指针进入函数 { strcpy(str, "world"); //非法访问 printf(str); } }
错误程序修改(使用二级指针)
void test(char** p , int num)
{
*p = (char*)malloc(num);
}
int main()
{
char* str = NULL;
test(&str,100);
strcpy(str,"hello world");
printf(str);
free(str);
str = NULL;
}
标签:进阶,str,int,free,C语言,内存,动态内存,NULL,ptr
From: https://blog.csdn.net/paradiso989/article/details/136951903