动态内存
1.内存泄漏
如果不再使用已分配的内存却没有将其释放就会发生内存泄漏
- 丢失内存地址: 同一个指针被malloc()函数多次赋值导致之前的赋值的内存地址丢失; 指针赋值为null导致内存地址丢失
- 隐式内存泄漏
2.动态内存分配函数
//malloc函数原型
void* malloc(size_t);
//如果malloc的参数是0,其行为是实现相关的:可能返回NULL指针,也可能返回一个指向分配了0字节区域的指针。
//如果malloc函数的参数是NULL,那么一般会生成一个警告然后返回0字节
//当malloc无法分配内存时会返回NULL,在使用它返回的指针之前先检查NULL是不错的做法
int *pi = (int*) malloc(sizeof(int));
if(pi != NULL) {
// 指针没有问题
} else {
//无效指针
}
//初始化静态或全局变量时不能调用函数
static int *pi;
pi = malloc(sizeof(int));
//calloc在分配的同时清空内存将内容置为0
void *calloc(size_t numElements, size_t elementSize);
//用malloc函数和memset函数可以得到同样的结果
/*
memset函数会用某个值填充内存块。
第一个参数是指向要填充的缓冲区的指针,
第二个参数是填充缓冲区的值,
第三个参数是要填充的字节数
*/
int *pi = malloc(5 * sizeof(int));
memset(pi, 0, 5* sizeof(int))
//realloc函数会重新分配内存,第一个参数是指向原内存块的指针,第二个是请求的大小
void *realloc(void *ptr, size_t size);
//free函数
void free(void *ptr);
3.迷途指针
指针指向的地址已被释放,但指针仍在引用原始内存的指针,成为迷途指针
int *p1 = (int*) malloc(sizeof(int));
*p1 = 5;
int *p2;
p2 = p1;
free(p1);
//p1,p2成为迷途指针
int *pi;
...
{
int tmp = 5;
pi = &tmp;
}// 这里pi变成了迷途指针
foo();
//处理方法
//释放指针后置为NULL,后续使用这个指针会终止程序.
//有些系统(运行时或调试系统)会在释放后覆写数据.在不抛出异常的情况下,如果程序员在预期之外的地方看到这些值,可以认为程序可能在访问已释放的内存
//用第三方工具检测迷途指针和其他问题
4.垃圾回收
-
资源获取即初始化(Resource Acquisition Is Initialization,RAII): 即使有异常发生,这种技术也能保证资源的初始化和后续的释放。分配的资源最终总是会得到释放
-
异常处理函数: try块包含任何可能在运行时抛出异常的语句。不管有没有异常抛出,都会执行finally块,因此也一定会执行free函数
void exceptionExample() { int *pi = NULL; __try { pi = (int*)malloc(sizeof(int)); *pi = 5; printf("%d\n",*pi); } __finally { free(pi); }
网友评论