常见的内存错误【四】

9.  分配/释放不配对

    大家都知道malloc要和free配对使用,new要和delete/delete[]配对使用,重载了类new操作,应该同时重载类的delete/delete[]操作。这些都是书上反复强调过的,除非当时晕了头,一般不会犯这样的低级错误。
    而有时候我们却被蒙在鼓里,两个代码看起来都是调用的free函数,实际上却调用了不同的实现。比如在Win32下,调试版与发布版,单线程与多线程是不同的运行时库,不同的运行时库使用的是不同的内存管理器。一不小心链接错了库,那你就麻烦了。程序可能动则崩溃,原因在于在一个内存管理器中分配的内存,在另外一个内存管理器中释放时出现了问题。

10. 返回指向临时变量的指针

    大家都知道,栈里面的变量都是临时的。当前函数执行完成时,相关的临时变量和参数都被清除了。不能把指向这些临时变量的指针返回给调用者,这样的指针指向的数据是随机的,会给程序造成不可预料的后果。
    下面是个错误的例子:

    char* get_str(void)
    {
        char str[] = {"abcd"};
        return str;
    }

    int main(int argc, char* argv[])
    {
        char* p = get_str();
        printf("%s/n", p);
        return 0;
    }

    下面这个例子没有问题,大家知道为什么吗?

    char* get_str(void)
    {
        char* str = {"abcd"};
        return str;
    }
    int main(int argc, char* argv[])
    {
        char* p = get_str();
        printf("%s/n", p);
        return 0;
    }
 
11. 试图修改常量

    在函数参数前加上const修饰符,只是给编译器做类型检查用的,编译器禁止修改这样的变量。但这并不是强制的,你完全可以用强制类型转换绕过去,一般也不会出什么错。
    而全局常量和字符串,用强制类型转换绕过去,运行时仍然会出错。原因在于它们是是放在常量区里面的,而常量区内存页面是不能修改的。试图对它们修改,会引发内存错误。
    下面这个程序在运行时会出错:

    int main(int argc, char* argv[])
    {
        char* p = "abcd";
        *p = '1';
        return 0;
    }
 
12. 误解传值与传引用

    在C/C++中,参数默认传递方式是传值的,即在参数入栈时被拷贝一份。在函数里修改这些参数,不会影响外面的调用者。如:

    #include <stdlib.h>
    #include <stdio.h>

    void get_str(char* p)
    {
        p = malloc(sizeof("abcd"));
        strcpy(p, "abcd");
        return;
    }

    int main(int argc, char* argv[])
    {
        char* p = NULL;
        get_str(p);
        printf("p=%p/n", p);
        return 0;
    }

    在main函数里,p的值仍然是空值。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值