分享

内存溢出总结:

 大道至简o 2016-01-20

内存溢出总结:

 

1.

 

内存分配未成功,却使用了它。

 

如果指针

P

是函数的参数,那么在函数的入口处用

assert(p 

!= 

NULL)

进行检查。如果是用

malloc

new

来申请内存,应该用

if(p 

== 

NULL)

或者

if(P != NULL)

来进行防错处理。

 

2.

 

内存分配虽然成功,但是尚未初始化就引用它。

(犯错的原因:

1.

没有初始化的观念;

误以为内存的缺省初值全为

0

,导致引用初值的错误(如数组)

 

3.

 

内存分配成功并且已经初始化,但操作越过了内存的边界。

(数据下标发生“多

1

”或

者“少

1

”的操作。特别是在

for

循环语句中,循环次数很容易搞错,导致数组越界)

 

4.

 

忘记了释放内存,造成内存泄漏。

(含这种错误的函数每次调用就丢失一块内存。刚刚

开始系统的内存充足,

可能看不到。

但程序突然有一次死掉,

系统出现提示:

内存耗尽)

动态内存的申请与释放必须配对,程序中

malloc

free

的使用次数一定要相同,否则

肯定有错误

(new/delete

同理

5.

 

释放了内存却继续使用它。

一:

程序中的对象调用关系过于复杂,

实在难以搞清楚某个

对象究竟是否已经释放了内存,

此时应该重新设计数据结构,

从根本上解决对象管理混

乱局面。二:函数

return

语句写错了,注意不要返回指向“栈内存”的“指针”或者

引用,因为该内存在函数体结束时被自动销毁。三、使用

free

delete

释放内存后,

没有将指针设置为

NULL

,导致产生“野指针”

 

 

规则:

 

 

malloc

new

申请内存后,

应该立即检查指针是否为

NULL

防止使用指针值为

NULL

的内存。

 

 

不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。

 

 

避免数组或者指针下标越界,特别当心发生“多

1

”或者“少

1

 

 

动态内存的申请与释放必须配对,防止内存泄漏。

 

 

free

delete

释放了内存之后,立即将指针设置为

NULL

,防止产生“野指针”

 

 

数组和指针之间区别:

 

1.

 

修改内容。

 

 

Char a[] = 

hello

  

A[0] = 

X0

  

Cout 

 

<< a << endl //

可以改变常量的值。

 

 

Char *p = 

world

  

 

//P

是指向常量的字符串,

 

P[0] = 

X

  //error,

指针

P

指向常量字符串

world

,常量字符串的内容是不可被修改

 

 

2.

 

内容复制与比较。

 

数组的复制:

 

Char a[] = 

hello

  

Char b[10]  

Strcpy(b, a); 

If (strcmp(b,a) == 0) 

 

指针

 

Int 

len = strlen(a); 

Char *p = (char *)malloc(sizeof(char) * (len + 1))  

If(NULL == p) 

 

Return 

 

-1  

Strcpy(p,a)  

 

// 

If(strcmpy(p,a) == 0) 

3.

 

指针参数如何传递内存。

 

 

Y

 

 

Void GetMemory1(char *p, int num) 

 

 

 

P = (char *)malloc(sizeof(char) * num)  

//

问题:

编译器总是要为函数的每个参数制作临时副本,

指针参数

p

的副本上

 

_p,

编译器使

 

_p = p .

如果函数体内的程序修改了

_p

的内容

就导致参数

P

的内容作

相应的修改

。这就是指针可以用作输出参数的原因。在本例中,

_p

申请了新的内

存,

只是把

_p

所指的内存地址改变了,但是

p

丝毫未变

。所以函数

GetMemory

不能输出任何东西,事实上,每执行一次

GetMemory

就会泄漏一块内存,因为没

有用

free

释放内存。

 

用指向指针的指针后解决这个问题:

 

Void GetMemory2(char **p, int num) 

 

*p = (char *)malloc(sizeof(char) * num)  

 

用函数返回值了解决:

 

Char *GetMemory3(int num) 

 

Char *p = (cahr * )malloc(sizeof(char) * num) 

 

 

Return p  

Void Test(void) 

 

Char *str = NULL  

 

GetMemory1(str, 100);//

申请内存错误

 

 

GetMemory2(&str, 100) //

注意参数是

&str

,而不是

str

 

 

Str = GetMemory3(100)  

 

Strcpy(str, 

hello

); 

 

4.

 

Free/delete,

只是把指针所指的内存释放掉,并没有把指针本身干掉。

 

5.

 

函数体内局部变量在函数结束时自动消亡。

但是局部指针变量,

消亡的时候它所指

的动态内存不一定一起消亡

.(

比如别的模块调用怎么办

)

1

、指针消亡了,并不表

示它所指的内存会被自动释放。

2

、内存被释放了,并不表示指针会消亡或者成了

NULL

指针。

 

6.

 

野指针,不是

NULL

指针,是指向“垃圾”内存的指针。形成的原因:

1

、指针变

量没有被初始化。任何指针变量刚刚被创建时不会自动成为

NULL

指针,它的缺省

值是随机的,

它会乱指一起。

所以,

指针变量在创建的同时应当被初始化,

要么将

指针设置为

NULL

,要么让它指向合法的内存。

Char *p = NULL  char *str =(char 

*)malloc(100) 2

、指针

P

free/delete

之后,没有被指为

NULL

,让人误认为

P

合法的指针。

3.

指针操作超越了变量的作用范围。

 

7.

 

MAlloc

free

C/C++

语言的标准库函数,

new/delete

C++

的运算符,它们都是

可以用于申请动态内存和释放内存。

 

对于非内部数据类型的对象而言,光

malloc

free

无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象

在消亡之前要自动执行析构函数。由于

malloc/free

是库函数而不是运算符,不再

编译器控制的权限之内,不能够把执行构造函数和析构函数的任务强加与

malloc/free

不要企图用

malloc/free

来完成动态对象的内存管理,

应该用

new/delete.

由于内部数据类型的

对象

没有构造与析构的过程,对他们而言

malloc/free

new/delete

是等价的。

New/delete

的功能完全覆盖了

malloc/free

的功能,保留的

原因是

C++

经常需要调用

C

函数,

c

程序只能用

malloc/free

动态管理内存。

如果

free

释放“

new

创建的动态对象”

,那么该对象因无法执行析构函数而可能导致

程序出错。

 

8.

 

内存申请不到。

1

判断指针是否为

NULL

如果是则马上用

return

语句终止本函数。

Void Func(void) 

 

 

*a = new A  

 

If(NULL == a) 

 

 

 

Return  

B

.判断指针是否为

NULL

,如果是则马上用

exit(1)

终止整个程序的运行。

 

Void func(void) 

 

A *a = new A  

 

If (NULL == a) 

 

 

cout << 

memory Exhausted

 <<endl  

Exit(1)  

 

C:

new

malloc

设置异常处理函数。

 

1.

 

Malloc /free

的使用要点

 

函数原型:

void *malloc(size_t size)  //

malloc

申请一块长度为

length

的整数

类型的内存。

Int *p = (int *) malloc(sizeof(int) *length) 

 

A:malloc

返回值的类型是

void * ,

所以在调用

malloc

时要显式地进行类型转换,

void*

转换成所需的指针类型。

 

B:malloc

函数本身并不知道申请内存是什么类型,只关心内存自己总数。

 

2.

 

函数

free

的原型如下:

void free(void *memblock) 

指针

p

的类型以及指向的内

存容量事先都知道,所以

free(p)

能正确释放内存。如果

P

NULL

指针,那么

free

P

无论操作多少次都不会出现问题,如果

P

不是

NULL

指针,那么

free

P

连续操作两次就会导致程序运行出错。

 

 

3.

 

New/delete

要点。

 

Int *p2 = new int[length] 

因为

new

内置

sizeof

类型转换和

类型安全检查功能。

对于非内部数据类型的对象而言,

new

在创建动态对象的

同时完成了初始化工作。如果对象有多个构造函数,那么

new

的语句也可以

有多种形式。

 

 

A

:如果用

new

创建对象数组,那么只能使用对象的无参数构造函数。

 

Obj *objects = new obj[100]  //

创建

100

个动态对象。

 

不能写成

Obj *objects = new obj[100](1) //

创建

100

个动态对象同时赋初

值为

1. 

 

delete []objects //

正确的用法。

 

 

 

总结:

1.

多用指针。

 

 

 

 

 

 

 

 

2.

养成逐步调试的习惯。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多