c/c++整理--引用和指针(5)

一、什么是“野指针”

  “野指针”不是NULL指针,而是指向“垃圾”内存的指针,其成因主要为:指针变量没有被初始化,或指针p被free或者delete之后,没有置为NULL。


二、“野指针”的危害

下面程序有什么重大的bug?
short *bufptr;
short bufarray[20];
short var = 0x20;
*bufptr = var;
bufarray[0] = var;
第一行bufptr声明了一个指针,但没有初始化,这个时候bufptr是乱指的一个指针,即“野指针”,第四行取一个非法地址的值就会造成程序崩溃,甚至是段错误。


三、有了malloc/free,为什么还要new/delete

malloc/free是c++/c的标准库函数,new/delete是c++的运算符,都可以申请和释放堆内存。
对于内部的数据类型,如int、char等,malloc/free和new/delete都可进行申请和释放,但是对于c++中的类数据类型,malloc/free无法满足要求了,对象在销亡之前要执行析构函数,malloc/free是库函数不是运算符,不能把执行构造函数和析构函数的任务强加于其。


四、各种内存分配和释放的函数的联系和区别

malloc、calloc、realloc、free
(1)malloc与calloc的区别为1块和n块的区别。
(2)malloc的调用形式为(类型*)malloc(size),在堆内存中分配一块size大小的连续内存,返回该区域的首地址。此时内存中的值没有被初始化;
(3)calloc的调用形式为(类型*)calloc(n,size),在堆内存中分配n块size大小的连续内存,返回首地址,此时内存中的值被初始化为0;
(4)realloc的调用形式为(类型*)realloc(*ptr,size),将ptr的内存大小增大到size,新增的内存没有初始化。
(5)free的调用形式为free(void* ptr),释放ptr所指向的一块内存空间。


五、找错——动态内存的传递

#include <iostream>

using namespace std;

class Base
{
	char* name;
public:
	Base(char* classname)
	{
		name = new char[strlen(classname)];
		strcpy(name, classname);
	}
	~Base()
	{
		delete name;
	}
	char* copyname()
	{
		char newname[10] = "";
		strcpy(newname, name);
		return newname;
	}
	char* getname()
	{
		return name;
	}
};

class Subclass : public Base
{
public:
	Subclass(char* classname) : Base(classname)
	{
		
	}
};

int main()
{
	Base* pBase = new Subclass("test");
	printf("name:%s\n", pBase->getname());
	printf("new name: %s\n", pBase->copyname());
	
	return 0;
} 

这里strlen测得的大小为实际字符串大小小1,所以11行改为
name = new char[strlen(classname)+1];
其次,20行newname是在栈中的,函数结束后就被自动释放了,应该在堆中分配内存。改为
char *newname = new char[strlen(name)+1];


六、动态内存分配

#include <iostream>
#include <stdlib.h>
#include <string.h>

using namespace std;

void GetMemory(char *p, int num)
{
	p = (char*)malloc(sizeof(char)*num);
}

int main()
{
	char* str = NULL;
	GetMemory(str, 10);
	strcpy(str, "hello");
	
	return 0;
} 

这里的GetMemory函数有问题,GetMemory函数体中的p实际上是main函数中的str变量在GetMemtory函数栈中的一个备份,因为编译器总是为函数的每个参数制作临时的变量。因此,虽然在函数中重新分配了内存,但是返回main函数时,str还是NULL,14行出现段错误。
这里可以使用函数返回值来避免这个问题,
char * GetMemory(char *p, int num)
{
	p = (char*)malloc(sizeof(char)*num);
	return p;
}

.......

str = GetMemory(str, 10);


七、内存分配方式有几种

(1)从静态存储区分配。在程序编译时就已分配好,例:全局变量。
(2)从栈上分配。函数中的局部变量的存储单元可以在栈上分配,函数结束时,这些变量被自动释放。
(3)从堆上分配。用malloc或free申请内存,由程序员决定其生存周期,然后执行free或delete。







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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值