指针作为函数参数在C/C++中调试和探讨

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liquanhai/article/details/18811075

      新年的钟声马上就要敲响了,我们回忆过去,我们向往未来,我们脚踏实地的去仔细研究遇到的每个问题,这就是程序员的执着,再大的工程也会因为一点点小的疏忽而崩溃,以致功亏一篑。这篇博文主要是讨论函数传参中需要注意的问题,人人都会遇到,但是不一定都清楚明白。看完本文后,肯定会有收获,恍然大悟,原来是这样!


示例代码如下:

void GetMemory(char *p)
{
	p = new char[20];
}

void Test()
{
	char * str = NULL;
	GetMemory(str);
	strcpy(str,"hello,world");
	
	delete str;
	str = NULL;
}

每一个程序员在面试中都会遇到的问题,上面那段代码问题在哪里呢?

(1) 会造成内存泄漏

(2) 在strcpy会出现程序奔溃。

以下是具体的问题分析:

我们知道函数一般都是传值,即使是指针的值,也是一个数值而已。下面通过调试来看看str的值的变化:



第1步刚刚进入Test函数,str分配好地址0x0012f464,但是里面的值为0xcccccccc,即为没有初始化的值




第2步在Test函数中,str被赋值为NULL即,此时str的地址0x0012f464,但是里面的值为0x00000000,注意因为此时没有进入子函数GetMemory,所以p还没有分配内存




第3步进入子函数GetMemory中,str的值被传递给新申请的p。此时p的地址0x0012f384,但是里面的值为0x00000000




第4步在子函数GetMemory中,在堆上申请的 new char[20]返回的地址值保存在p中。此时p的值已经由之前的0x0012f384变为0x0035cf08;





第5步在跳出子函数GetMemory,返回到Test函数中,注意观察此时的变量状态:临时变量p的生命周期随着子函数GetMemory的结束一起结束了,并没有把新申请的new char[20]的地址传递到Test函数中来;str的值还是之前的,没有做任何改变

   回到文章开头的对这段代码的结论:

 (1)既然变量p已经被销毁,那么它保存的堆上申请的new char[20]的地址也会被丢失,造成了内存泄漏。

 (2)指针str的值还是0x00000000,str是个空指针,那么在执行到strcpy(str,"hello, world");时势必会出现程序奔溃。


   通过上面的一系列调试截图,我们知道函数传递时仅仅是传递的值。借用一位网友的总结:

“函数的参数进行值拷贝,即使传的是指针,也的对指针(即指针里存的地址)的拷贝。”

遇到搞不清楚的时候勤动手,多调试,肯定会搞明白的。

    可能聪明的你还想追问,那指针做函数参数是怎么用的呢?

   其实我们之所以使用指针,仅仅是因为通过它作为纽带可以找到我们想操作的东西。

大多数时候都是类似的这种用法:

void GetMemory(char *p)
{

(1)*p='N';

(2)p[0]='N'

(3)*(p++)='N';

}

之类用法来修改指针指向的地址里面的变量值,而不是修改指针的值。更多的知识请读者自己在使用中慢慢去体会了。

  

  啰啰嗦嗦的说了那么多,最终是想改造上面的那段程序实现既能解决内存泄漏,又能达到复制hello,world到新内存的目的。我们只需修改一个地方即可,传指针改为传引用

void GetMemory(char *&p)
{
	p = new char[20];
}

void Test()
{
	char * str = NULL;
	GetMemory(str);
	strcpy(str,"hello,world");
	
	delete str;
	str = NULL;
}





参考网址列表:

http://www.cppblog.com/mzty/archive/2006/07/07/9531.html

http://www.cnblogs.com/nerohwang/p/3481725.html



猜你喜欢

转载自blog.csdn.net/liquanhai/article/details/18811075
今日推荐