动态内存管理(下)

动态内存管理(上)-优快云博客(malloc, realloc, calloc, free函数的用法以及注意事项等知识点)。

动态内存管理(中)-优快云博客(常见的内存出错问题)

---------------------------------------------------------------------------------------------------------------------------------前两节复习了动态内存函数和常见内存出错的问题。 这节主要分析几个容易出错的问题加深印象。

目录

题目一:空指针解引用问题

题目二: 野指针的访问

 题目三:二级指针修改指针实参

题目四:free后忘记将指针置空


题目一:空指针解引用问题

void GetMemory(char* p)
{
     p = (char*)malloc(100);
}
void Test(void)
{
     char* str = NULL;
     GetMemory(str);
     strcpy(str, "hello world");
     printf(str);
}

int main() 
{
     Test();
     return 0;
}

 请看这么一道题, Test()哪里出错了呢?

其实这里在str函数传参时是穿的NULL值过去给p, 修改p并没有修改str, str仍为NULL, 后续对str赋值是对控制真的解引用。如下: 

题目二: 野指针的访问

char *GetMemory(void)
{
        char p[] = "hello world";
        return p;
}
void Test(void)
{
        char *str = NULL;        
        str = GetMemory();
        printf(str);
}
int main()

{

        Test();

        return 0;

}

请问Test()函数哪里出错了呢?

这一题是野指针的解引用问题。 野指针。 GetMemory函数虽然返回了一个指针, 但是这个指针是在它自己的栈帧空间申请的一处空间, 而GetMemory在调用完毕之后销毁函数栈帧, 操作系统回收内存, 返回的指针所指向的就是一块没有权限访问的内存了, 也就是野指针。

如图: 

 题目三:二级指针修改指针实参

void GetMemory(char **p, int num)
{
        *p = (char *)malloc(num);
}
void Test(void)
{
        char *str = NULL;
        GetMemory(&str, 100);
        strcpy(str, "hello");
        printf(str);
}
 int main()

{

        Test();

        return 0;

}

 请问Test函数会有什么结果呢?

 这道题是题目一的改正, 这个时候已经能够很好的打印hello了。 

题目一我们知道是因为str传值, 修改形参不会修改实参。 而这个题将str的地址传送了过去, 想当于对于str的传址调用。 并且str是一个指针变量。 所以接收使用的二级指针。 

关系如图:

题目四:free后忘记将指针置空

void Test(void)
{
        char *str = (char *) malloc(100);
        strcpy(str, "hello");
        free(str);
        if(str != NULL)
        {
                strcpy(str, "world");
                printf(str);
        }
}

int main()

{

        Test();

        return 0;

}

请问Test中结果是什么?

会报错, 这又是野指针解引用问题。 

str虽然free了, 但是str这个时候指向的还是刚刚堆区申请的那处空间的首地址。 这块地址不是空指针, 进入if语句后strcpy发生野指针访问问题。 

如图:
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值