首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

C指针作为参数的程序分析,该怎么解决

2013-01-18 
C指针作为参数的程序分析我在看林锐博士的《高质量程序设计指南》这本书的时候,书最后面有一份习题,上面有一

C指针作为参数的程序分析
我在看林锐博士的《高质量程序设计指南》这本书的时候,书最后面有一份习题,上面有一个这样的题目:

有如下两个程序:

[程序1:]


#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h>

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

int main()
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello world!");
printf(str);
printf("\n");
system("pause");
return 0;
}


程序1可以正常的输出“hello world”
但是会“内存泄露”
但是请看程序2



[程序2:]

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h>

void GetMemory(char *p)
{
p = (char *)malloc(100);
}

int main()
{
char *str = NULL;
GetMemory(str);
strcpy(str, "hello world!");
printf(str);
printf("\n");
system("pause");
return 0;
}


程序2运行时程序会崩溃





问:有点不明白用malloc动态分配内存,两个程序中GetMemory函数内部分别是怎么实现的?还请各位解释清楚一点,我现在是似懂非懂的感觉,懂一点,但是不能深层次的解释问题。
[解决办法]
程序1 malloc没有free
程序2 str没有分配内存
[解决办法]
第二个实际上只是为形参分配了内存,实参并未分配到内存,因为在进入函数GetMemory时,形参指针 p 会成为实参指针 str 的一份复制(值拷贝),所以函数 GetMemory 执行后,形参 p 指向了分配到的内存,而实参 p 的值没有改变,自然在后面向 str 指向的内存拷贝字符串的时候必崩溃无疑。
详细的描述可以参考 http://blog.csdn.net/zhcosin/article/details/8275603
[解决办法]
有点不明白用malloc动态分配内存,两个程序中GetMemory函数内部分别是怎么实现的?
明白兩點
1.指針的概念,
2.c語言函數参數的傳遞,

void GetMemory(char **p, int num)
{
    *p = (char *)malloc(num);
}
void GetMemory(char *p)
{
    p = (char *)malloc(100);
}
1. p都是GetMemory的局部變量,函數運行結束,p是不存在的。
2. char **p. 這個p表示一個指針的地址,有這個地址,你就可以向這個地址的内存空間放數據。
3. GetMemory(&str, 100);取得變量str的地址,傳給p
*p = (char *)malloc(num); 將分配好的空間的地址,放到地址p所指的内存空間処,其實就是str所佔的内存空間, 這樣str的就改變了。

4. 明白了上面的,GetMemory(str);就很容易理解了。


[解决办法]
传参传的是拷贝,这点弄明白就可以举一反三了。第二个情况内存是在拷贝的地址上分配的,str = NULL并未改变。
[解决办法]
函数参数的传递方式:地址传递和值传递。
程序1是地址传递,也就是传进来一个地址,此时的形参是实参的一个拷贝,但这并没有影响到修改该地址所指向的内存中的内容,所以程序1可以输出结果,但是程序没有free,所以会存在内存泄露
程序2是值传递,传进来一个实参的副本,也就是拷贝了一个地址,此时在函数体重对这个地址重新赋值了,但是并没有影响到实参的变换,所以此时实参地址指向的内存中的内容还是空的。
[解决办法]
实际上这是参数传递的问题,看起来是传地址,其本质是传值。

str的值(NULL)传给了p,p只是str的一个复印件,复印件的内容发生了改变(指向了新的地址),

但原件str的值是不会发生改变的(还是NULL).

所以你的strcpy(str, "hello world!");是错误的!
[解决办法]
第一个由于没有手动释放内存自然会有内存泄露
第二个就是传参的话,也是传递过去一个智者你的副本,申请的空间只是给这个副本,并且这个自定义函数没有返回值的,要是申请完毕了然后返回该指针还是可以的
这样就行了
#include<stdio.h>
#include<string.h>


#include<stdlib.h>

 
char *GetMemory(char *p)
{
    p = (char *)malloc(100);
return p;
}
 
int main()
{
    char *str = NULL;
    str=GetMemory(str);
    strcpy(str, "hello world!");
    printf(str);
    printf("\n");
    system("pause");
    return 0;
}


[解决办法]
对了
忘了释放内存
应该是这样
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

 
char *GetMemory(char *p)
{
    p = (char *)malloc(100);
return p;
}
 
int main()
{
    char *str = NULL;
    str=GetMemory(str);
    strcpy(str, "hello world!");
    printf(str);
    printf("\n");
free(str);
    system("pause");
    return 0;
}

热点排行