乐趣区

关于c:C内存操作经典问题分析二

常见内存谬误

构造体成员指针未初始化
构造体成员指针未调配足够的变量
内存调配胜利,但并未初始化
内存操作越界

例子 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 时,程序可能解体
退出移动版