指针动态申请内存的错误有几种解释,
有如下几种:
相信我们都知道传值调用参数时,不改变实际参数的值。原理:形参是实参的一个copy(副本),而不是指向同一块内存地址。于是用指针或引用就可以解决这个问题,大多数时候还会节省内存开销,因为不用作副本拷贝。
这样一个例子:
void test(char *ps)
{
ps = (char *)malloc(10*sizeof(char));
}
int main(void)
{
char *str = NULL;
test(str);
strcpy(str, "abcd");
cout << str << endl;
return 0;
}
用指针作为参数,在函数内部申请动态内存,结果该程序会崩溃。
原因其实很简单,ps申请了内存,也就是改变了ps这个副本的内容(即申请的动态内存地址),但函数返回了,原形参ps的内容没有任何改变,就如同上述的传值一样,ps的内容仍为NULL,于是出错。
而且不但出错,该程序还会出现内存泄露的问题,因为malloc的这块内存未释放,也无法释放了。
2
试图用指针参数申请动态内存
毛病出在函数getmemory 中.编译器总是要为函数的每个参数制作临时副本,指针
参数p 的副本是 _p,编译器使 _p = p.如果函数体内的程序修改了_p 的内容,就导致
参数p 的内容作相应的修改.这就是指针可以用作输出参数的原因.在本例中,_p 申请
了新的内存,只是把_p 所指的内存地址改变了,但是p 丝毫未变.所以函数getmemory
并不能输出任何东西.事实上,每执行一次getmemory 就会泄露一块内存,因为没有用
free 释放内存.
感觉上面说的不是很好理解。我把我的理解写一下。
像第二种说法所说,编译器总是要为函数的每个参数制作临时副本,指针
参数p 的副本是 _p,编译器使 _p = p.这就是指针可以用作输出参数的原因.
把这个原因解释一下:
比如你传入一个指针p指向的地址是0xffff,那么复制出来的_p指向的地址也是0xffff,
只不过p和_p本身的存储地址是不一样的。例如p存在内存地址为1的地方,而_P存在地址2这个地方,
但二者指向的内存地址是一致的,所以当修改了_p所指向的地址的内容的时候(也就是修改0xffff,这个地址的内容的时候)
p所指的内存内容也改变了,所以该变的内容就可以传出来了。函数结束_p被删除,但是这不影响p指向内容的修改。
在申请动态内存这个放面呢,是不一样的。
在函数外p为NULL,
在函数内申请动态内存,相当于_p=(char *)malloc(10*sizeof(char));
这样把新申请的内存地址赋给了_p,比如新申请的内存地址为0xaaaa,那么现在_p所指向的内存地址就是0xaaaa,
但是这不能影响p所指向的地址,因为p和_p是在不同的内存地址存放的,现在只有_p的内容改变了,
也就是说内存地址为2的这块地址的内容发生了改变。
p所指的内存地址仍为NULL.所以不能申请出来动态内存。