42-内存操作经典问题分析二

注:博客中内容主要来自《狄泰软件学院》,博客仅当私人笔记使用。

测试环境:Ubuntu 10.10

GCC版本:4.4.5

 

一、常见内存错误

1) 结构体成员指针未初始化

2) 结构体成员指针未分配足够的内存

3) 内存分配成功,但并未初始化

4) 内存操作越界

 

实例分析
常见内存错误
42-1.c
#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 )    //判断size是不是偶数
    {
        return;         //这里可能产生内存泄露,导致35行无法释放free
    }
    
    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));
    
    test(p, 5);
    
    free(p);     //重复释放两次指针,导致内存崩溃
    
    func(9);
    func(10);
       
    return 0;
}

操作:

1) gcc 42-1.c -o 42-1.out编译正确,打印结果:

0
0
0
0
0
*** Error in `./42-1.out': double free or corruption (fasttop): 0x09f09008 ***
Aborted (core dumped)

分析:

        重复释放p指向的内存。

 

2) 注释掉free(p):

实例分析
常见内存错误
42-1.c
#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 )    //判断size是不是偶数
    {
        return;         //这里可能产生内存泄露,导致35行无法释放free
    }
    
    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));
    
    test(p, 5);
    
    //free(p);     //重复释放两次指针,导致内存崩溃
    
    func(9);
    func(10);
       
    return 0;
}

gcc 42-1.c -o 42-1.out编译正确,打印结果:

0
0
0
0
0
0
1
2
3
4
5
6
7
8
9

分析:

        func(10)内容没有打印,说明func(10)函数中申请的内存没被释放,造成内存泄露。

注:这个例子体现,多次释放内存和内存泄露

 

42-2.c
#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++)
    {
        d1.p[i] = 0; 
    }
    //内存越界,申请并初始化内存数据为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;
}

操作:

1) gcc 42-2.o 42-2.out编译错误:

42-2.c:18:3: error: ‘dl’ undeclared (first use in this function)
   dl.p[i] = 0;
   ^
错误:dl没有被声明   
42-2.c:18:3: note: each undeclared identifier is reported only once for each function it appears in

 

二、内存操作的交通规则

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

int* p = (int*)malloc(56);
if(p != NULL)
{
    //Do something here!
}

free(p);

 

2) free指针之后必须立即赋值为NULL为了杜绝野指针,NULL的错误好查)。

int* p = (int*)malloc(20);

free(p);
p = NULL;

// ...
// ......
// .........
// ............
// ...............
if( p != NULL)
{
    // Do something here!
}

 

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

void print(int* p,int size)    //size为长度信息
{
    int i = 0;
    char buf[128] = {0};
    snprintf(buf,sizeof(buf),"%s","D.T.Software"); //sizeof(buf)内存长度信息
    for(i = 0;i<size;i++)
    {
        printf("%d\n",p[i]);
    }
}

 

4) malloc操作和free操作必须匹配,防止内存泄露和多次释放。

void func()
{
    int* p = (int*)malloc(20);    //二者匹配存在
    free(p);
}

int main()
{
    int* p = (int*)malloc(40);    //二者匹配存在
    func();
    free(p);
    return 0;
}

 

小结:

1) 内存错误的本质源于指针保存的地址为非法制

    - 指针变量未初始化,保存随机值

    - 指针运算导致内存越界

2) 内存泄露源于malloc和free不匹配

    - 当malloc次数多于free时,产生内存泄露

    - 当malloc次数少于free时,程序可能崩溃

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值