常见内存错误

结构体成员指针未初始化
结构体成员指针未分配足够的变量
内存分配成功,但并未初始化
内存操作越界

例子42-1:

#include "stdio.h"
#include "malloc.h"
void test(int* p,int size)
{
    int i = 0;
    for(i = 0; i < size; i++)
    {
        printf("%d\n",p[i]);
    }
//    free(p);
}
void func(unsigned int size)
{
     int *p = (int*)malloc(size *sizeof(int));
     int i = 0;
     if(size % 2 != 0)
     {
        return;
     }
     for(i = 0; i < size; i++)
     {
        p[i] = i;
        printf("%d\n",p[i]);
     }
     free(p);
}
int main()
{
    int* p = (int*)malloc(5 * sizeof(int));  //在main函数里面申请的动态内存,就要在main函数里面释放
    test(p , 5);
    free(p);
    func(9);
    func(9);
    return 0;
}

输出结果:

func函数会产生内存泄漏,如果是基数就会直接return,导致内存没有释放,造成内存泄漏

例子42-2:

#include "stdio.h"
#include "malloc.h"
struct Demo
{
    char *p;
}
int main()
{
    struct Demo d1;
    struct Demo d2;
    char i = 0;
    for(i = 'a';i < 'z';i ++) 
    {
        d2.p[i] = 0;
    }
    d2.p = (char*)calloc(5,sizeof(char));
    printf("%s\n",d2.p);
    for(i = 'a';i < 'z';i ++) //内存越界
    {
        d2.p[i] = i;
    }
    free(d2.p);
    return 0;
}

内存操作的规则

规则一:

动态内存申请之后,应该立即检查指针值是否为NULL,防止使用NULL指针。

int* p = (int*)malloc(56);
if(p != NULL)
{

}
free(p);
规则二:

free指针之后必须立即赋值为NULL

int* p = (int*)malloc(20);
free(p);
p = NULL;
//......
//......
if(p != NULL)
{

}
规则三:

任何与内存操作相关的函数必须带长度信息

void print(int* p,int size)
{
    int i = 0;
    char buf[128] = {0};
    snprintf(buf,sizeof(buf),"%s","D.T.Software");
    for(i = 0;i < size; i++)
    {
        printf("%d\n",p[i]);
    }
}
规则四:

malloc操作和free操作必须匹配,防止内存泄漏和多次释放。不要跨函数释放内存。

void func()
{
    int* p = (int*)malloc(20);
    free(p);
}
int main()
{
    int* p = (int*)malloc(20);
    func();
    free(p);
    return 0;
}

小结:

内存错误的本质源于指针保存的地址为非法值
指针变量未初始化,保存随机值
指针运算导致内存越界
内存泄漏于malloc和free不匹配
当malloc次数多于free时,产生内存泄漏
当malloc次数少于free时,程序可能崩溃

YingLi
6 声望4 粉丝

From zero to hero.