Chapter2.h
#ifndef __CHAPTER_2_
#define __CHAPTER_2_
/*《深入理解C指针》学习笔记 -- 第二章*/
/*
内存泄露的两种形式
1.忘记回收内存
2.内存地址丢失
*/
void __memory_leak_test();
/*
内存操作的几个函数
malloc
alloc
realloc
free
*/
void __memory_function_test();
#endif
Chapter2.cpp
#include "Chapter2.h"
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
/*
内存泄露的两种形式
1.忘记回收内存
2.内存地址丢失
*/
void __memory_leak_test()
{
/*申请了内存但是忘记了回收不用的内存*/
int* p_test1 = (int*)malloc(sizeof(int));
*p_test1 = 1;
// do_something_to : p_test1
/*当不需要再使用 p_test1 时,应该及时释放内存,并赋值 NULL*/
/*
free(p_test1);
p_test1 = NULL;
*/
/*内存地址在程序中丢失了,导致没有办法释放掉申请(堆中)的内存*/
int* p_test2 = (int*)malloc(sizeof(int));
*p_test2 = 2;
// do_something_to : p_test2
/*当不需要再使用 p_test2 时,应该及时释放内存,并赋值 NULL*/
/*
free(p_test2);
p_test2 = NULL;
*/
/*但是这个时候,又重新申请了别的内存,导致,原来的内存地址丢失了*/
p_test2 = (int*)malloc(sizeof(int));
/*不需要使用这块内存后,应该显示的释放内存*/
free(p_test2);
p_test2 = NULL;
}
void __memory_function_test()
{
/*
malloc 函数用于分配内存,返回 void* 类型的指针,指向分配内存的初始地址,
但是不对这块内存进行初始化的操作
当内存申请失败时,返回NULL
*/
int* p_test1 = (int*)malloc(sizeof(int));
/*
如果申请的内存比较大,那么需要判断是是否申请失败,一般申请小的内存块不需要这样的操作
*/
assert(p_test1 != NULL);
//do_something_to_p_test1
/*使用完内存后应该及时释放,避免内存泄露*/
free(p_test1);
/*
calloc 函数,从堆上分配内存,与 malloc 函数的不同之处在于
它会对申请的内存进行清零的操作
当内存申请失败时,返回NULL
*/
int* p_test2 = (int*)calloc(2, sizeof(int));
/*
上面的操作可以利用 malloc 和 memset 实现
int *p_test2 = (int*)malloc(2 * sizeof(int));
memset(p_test2, 0, 2 * sizeof(int));
*/
/*
如果申请的内存比较大,那么需要判断是是否申请失败,一般申请小的内存块不需要这样的操作
*/
assert(p_test2 != NULL);
//do_something_to_p_test2
/*使用完内存后应该及时释放,避免内存泄露*/
free(p_test2);
/*
realloc 函数,一般用于对原来申请的内存做处理,申请更大的内存,或者缩小内存
1.如果参数为0,那么代表释放内存,就好像是使用 free 一样
2.如果申请的内存比当前分配的内存小,那么多余的内存会还给堆
3.如果申请的内存比当前分配的内存大,如果可能会紧挨着当前的内存的区域分配新的更大的内存,
否则,就在堆的其他区域分配并把旧的内存复制到新的区域
*/
char* p_test3;
char* p_test4;
char* p_test5;
p_test3 = (char*)malloc(8 * sizeof(char*));
printf("p_test3 address is : %x\n", p_test3);
p_test4 = (char*)realloc(p_test3, 64 * sizeof(char*));
printf("p_test4 address is : %x\n", p_test4);
p_test5 = (char*)realloc(p_test4, 65 * sizeof(char*));
printf("p_test5 address is : %x\n", p_test5);
/*
上述例子的运行结果如下:
p_test3 address is : 53a848
p_test4 address is : 53a8e0 重新找了一个新的区域分配更大的内存
p_test5 address is : 53a8e0 在原来的内存上面分配更大的内存
*/
/*
不要重复释放内存,否则结果是未定义的,例外是释放空指针(NULL)
*/
int* p_test6 = (int*)malloc(sizeof(int));
/*
free(p_test6); 这里是正确的操作
free(p_test6); 这里就会出现问题,因为释放了已经释放的内存
*/
/*
free(p_test6); 这里是正确的操作
p_test6 = NULL;
free(p_test6); 这里虽然是多次释放,但是前一步操作已经给指针赋值 NULL,free 不会出现问题
*/
}