关于就是realloc函数返回的指针的两种不同的情况。
【情况1 】
要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。
- realloc函数此时的返回值是旧的空间的起始地址
【情况2】
原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址。 且realloc函数有三个特点
- realloc函数会将旧的空间的数据,拷贝到新的空间里
- realloc函数拷贝完成后,会将旧的空间释放掉
- realloc函数此刻的返回值不是原来的地址,而是新的空间的起始地址
关于原地和异地扩容的验证:
【原地扩容】
#include<stdio.h> #include<stdlib.h> int main() { int* p1 = (int*)malloc(40); int* p2 = (int*)realloc(p1,80);//扩容40 printf("p1=%p\n", p1); printf("p2=%p", p2); return 0; }
【异地扩容】
#include<stdio.h> #include<stdlib.h> int main() { int* p1 = (int*)malloc(40); int* p2 = (int*)realloc(p1,800);//扩容760 printf("p1=%p\n", p1); printf("p2=%p", p2); return 0; }
当然除此之外,realloc还可以当成malloc来使用,只要传空指针即可。
所以所以 ptr可以为空指针NULL
#include<stdio.h> #include<stdlib.h> int main() { int* ptr = (int*)realloc(NULL, 10 * sizeof(int)); if (ptr == NULL) { perror("realloc"); return 1; } free(ptr); ptr = NULL; return 0; }
常见的动态内存错误
- 对NULL指针的解引用操作
- 对动态开辟空间的越界访问
- 对非动态开辟内存使用free释放
- 使用free释放一块动态开辟内存的一部分
- 对同一块动态内存多次释放
- 动态开辟内存忘记释放(内存泄漏)
接下来我们一个一个纠错!
NO1.
//对NULL指针的解引用操作 void test() { int* p = (int*)malloc(40); //不做返回值的判断,就可能是使用空指针解引用 *p = 20;//如果p的值是NULL,就会有问题 free(p); }
【修改】加上返回值的判断
#include<stdio.h> void test() { int* p = (int*)malloc(40); if (p == NULL) { perror("malloc"); return 1; } *p = 20; free(p); } int main() { test(); return 0; }
NO2.
//对动态开辟空间的越界访问 #include<stdio.h> void test() { int i = 0; int* p = (int*)malloc(10 * sizeof(int)); if (NULL == p) { perror("malloc"); return 1; } for (i = 0; i <= 10; i++) { *(p + i) = i;//当i是10的时候越界访问 } free(p); p = NULL; } int main() { test(); return 0; }
【修改】不越界即可
#include<stdio.h> void test() { int i = 0; int* p = (int*)malloc(10 * sizeof(int)); if (NULL == p) { perror("malloc"); return 1; } for (i = 0; i < 10; i++) { *(p + i) = i;//当i是10的时候越界访问 } free(p); p = NULL; } int main() { test(); return 0; }
NO3.
//对非动态开辟内存使用free释放 #include<stdio.h> void test() { int a = 10; int* p = &a; free(p); p = NULL;//err } int main() { test(); return 0; }
【修改】不可以哈,删去free
//对非动态开辟内存使用free释放 #include<stdio.h> void test() { int a = 10; int* p = &a; } int main() { test(); return 0; }
NO4.
//使用free释放一块动态开辟内存的一部分 //示例1 #include<stdio.h> void test() { int* p = (int*)malloc(100); p++; free(p);//p不再指向动态内存的起始位置 } int main() { test(); return 0; } //示例2 #include<stdio.h> #include<stdlib.h> int main() { int* p = (int*)calloc(10, sizeof(int)); if (p == NULL) { perror("calloc"); return 1; } //赋值 int i = 0; for (i = 0; i < 5; i++) { *p = i; p++; } //0 1 2 3 4 0 0 0 0 0 for (i = 0; i < 5; i++) { printf("%d ", p[i]); } free(p);//只是释放了后面五个0 p = NULL; return 0; }
【修改】不要让p移动,想移动就另外设置一个指针让它去移动。养成好习惯不要动起始的指针
//示例1 #include<stdlib.h> #include<stdio.h> void test() { int* p = (int*)malloc(100); int* ps = NULL; if (p == NULL) { perror("malloc"); return 1; } else { ps = p; } ps++; free(p); p = NULL;//p不再指向动态内存的起始位置 } int main() { test(); return 0; } //示例2 #include<stdio.h> #include<stdlib.h> int main() { int* p = (int*)calloc(10, sizeof(int)); if (p == NULL) { perror("calloc"); return 1; } //赋值 int i = 0; for (i = 0; i < 5; i++) { p[i] = i; } //0 1 2 3 4 0 0 0 0 0 for (i = 0; i < 5; i++) { printf("%d ", p[i]); } free(p);//只是释放了后面五个0 p = NULL; return 0; }
NO5.
//对同一块动态内存多次释放 #include<stdlib.h> #include<stdio.h> void test() { int* p = (int*)malloc(100); free(p); free(p);//重复释放 } int main() { test(); return 0; }
【修改】不要多次释放
#include<stdlib.h> #include<stdio.h> void test() { int* p = (int*)malloc(100); free(p); } int main() { test(); return 0; }
#include<stdlib.h> #include<stdio.h> void test() { int* p = (int*)malloc(100); free(p); p = NULL; free(p);//ok } int main() { test(); return 0; }
NO6.
//动态开辟内存忘记释放(内存泄露) //示例1 #include<stdlib.h> #include<stdio.h> void test() { int* p = (int*)malloc(100); if (NULL != p) { *p = 20; } } int main() { test(); while (1);//忘记释放 } //示例2 #include<stdlib.h> #include<stdio.h> void test() { int* p = (int*)malloc(100); if (NULL != p)//这里直接跳出循环 { *p = 20; } free(p);//无用 p = NULL; } int main() { test();//调用完成 malloc申请的空间还在 //没有忘记释放。但是释放没有用 while (1);//死循环程序退出不了 }
【修改】 忘记释放或在函数内部释放了但是没有使用都会造成内存泄露
#include<stdlib.h> #include<stdio.h> int* test() { int* p = (int*)malloc(100); if (NULL != p) { *p = 20; } return p; } int main() { int *p=test(); free(p); p = NULL; while (1);//忘记释放 }
动态开辟的空间一定要正确释放!!
✔✔✔✔✔最后,感谢大家的阅读,若有错误和不足,欢迎指正!下篇博文我们讲解几道相关笔试题
代码------→【gitee:唐棣棣 (TSQXG) - Gitee.com】
联系------→【邮箱:2784139418@qq.com】