内存泄露与破坏
C++的两个主要问题就是内存泄露与损害.内存泄露是指内存审请后没有释放,这种方式导致内存内存浪费最终可能会发生内存不够的错误.内存损坏是发生在程序将数据写在错误的内存位置,重写了那坏内存数据,没有成功更新到其目标位置。这两个问题都和指针相关.
虽然指针是一个强大的工具,但也可能是一个魔鬼.如果一个指针指向的内存已经被释放,或它偶而被一个非零的整型或浮点型赋值其会变的非常危险的脏内存,写操作随时会被结束。
然而如果一个指针被用来记录一块内存,可能非常容易的忘记释放,这样就会造成内存释放,这样就是内存泄露。
Accelerated C++ 的作者总结了可能由指针导致内存问题的问题如下:
拷贝一个指针但没有拷贝其指向的对象,如果有两个指针指向同一个对象就可能会发生二异性。
指针失效但没有释放其所指向的对象,导致内存泄露.
释放一个对象但没有释放其所指向的指针导致悬挂指针,这样会造成程序运行过程中的不可定义的行为。
创建指针时没有进行初始化,也可能导致不可定义的行为。
会崩溃的代码
崩溃的原因
1. 没有初始化指针操作-一个无效操作可能会对一个空指针进行读或写
2. 指针越界访问
3. 非法栈操作-程序可能会传递一个错误的指针类型到一个函数中。
4. 访问非常地址
5. 无限循环
6. 无效的对象指针
7. 没有检查内存审请失败
指针示例
本节我们通过示例来了解指针的特性.
定义结构如下:
struct account
{
char* name;
char id[8];
int balance;
}
我们定义account 的对象如下:
account Customer[4];
C++的两个主要问题就是内存泄露与损害.内存泄露是指内存审请后没有释放,这种方式导致内存内存浪费最终可能会发生内存不够的错误.内存损坏是发生在程序将数据写在错误的内存位置,重写了那坏内存数据,没有成功更新到其目标位置。这两个问题都和指针相关.
虽然指针是一个强大的工具,但也可能是一个魔鬼.如果一个指针指向的内存已经被释放,或它偶而被一个非零的整型或浮点型赋值其会变的非常危险的脏内存,写操作随时会被结束。
然而如果一个指针被用来记录一块内存,可能非常容易的忘记释放,这样就会造成内存释放,这样就是内存泄露。
Accelerated C++ 的作者总结了可能由指针导致内存问题的问题如下:
拷贝一个指针但没有拷贝其指向的对象,如果有两个指针指向同一个对象就可能会发生二异性。
指针失效但没有释放其所指向的对象,导致内存泄露.
释放一个对象但没有释放其所指向的指针导致悬挂指针,这样会造成程序运行过程中的不可定义的行为。
创建指针时没有进行初始化,也可能导致不可定义的行为。
会崩溃的代码
崩溃的原因
1. 没有初始化指针操作-一个无效操作可能会对一个空指针进行读或写
2. 指针越界访问
3. 非法栈操作-程序可能会传递一个错误的指针类型到一个函数中。
4. 访问非常地址
5. 无限循环
6. 无效的对象指针
7. 没有检查内存审请失败
指针示例
本节我们通过示例来了解指针的特性.
定义结构如下:
struct account
{
char* name;
char id[8];
int balance;
}
我们定义account 的对象如下:
account Customer[4];
我们审请了4个Customer对象:
我们赋一些值给这些对象成员:
Customer[0].balance = 1500;
Customer[2].name = strdup("Sam");
当我们做如下操作时内存会是什么样的呢?
Customer[3].name = Customer[0].id + 7;
当编译器看到:
Customer[0].id + 7;
这里7指的是偏移的个数.偏移的单位是从Customer[0].id是一个指针数组。所以Customer[3].name得到Customer[0].id+7的地址.
接下来我们用strcpy给id赋值:
strcpy(Customer[1].id,"1234567");
我们再做如下操作:
strcpy(Customer[3].name, "abcd");
因为Customer[3].name 是指向Customer[0].id + 7我们赋值了一个常量给这个地址.内存图如下:
我们从图中看到,我们给Customer[0] +7 赋值了5个字符串,其已经覆盖了我们已经审请的4个字节。