关于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时,程序可能解体

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理