欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

C语言-动态内存管理(三)-题目

最编程 2024-01-02 14:32:14
...

请问运行Test函数会有什么样的结果?

void GetMemory(char *p){
    p=(char*) malloc(100);
}
void Test(void){
    char *str=NULL;
    GetMemory(str);
    strcpy(str,"hello world");
    printf(str);
}
int main(){
    Test();
    return 0;
}

结果:

C语言-动态内存管理(三)_C

这段代码会崩溃掉,并且存在内存泄漏的问题。

接下来我们分析一下原因:

C语言-动态内存管理(三)_C_02

从main函数出发,调用Test我们进入Test函数,创建了个char类型指针变量str ,然后调用GetMemory,将str传过去,str值为NULL,那么p传入的参数也为NULL,然后执行malloc动态内存分配:

C语言-动态内存管理(三)_动态内存_03

开辟了一段空间首地址为:12ff21cd并返回给p,那么此时p指向了这段空间,到这里GetMemory的程序执行完毕。回到Test,我们会发现p虽然改了但是GetMemory已经结束p生命周期也已经结束了,并没有改变str的值。

所以此时str的值还是NULL。

str的值为NULL,并不是一个有效的地址。从NULL开始拷贝的时候会从这个地址自增,那必然会访问非法空间,那strcpy肯定是执行不成功的。

    strcpy(str,"hello world");

所以这里就会直接崩溃。

崩溃的原因:

所以这里的问题还是因为传递的是str的值而不是str的指针。所以并没有改变str的值,如果想要改变str的值那应该传递指向str的指针。应该是个二级指针。

内存泄漏因为:

str以值的形式传递给p,p是GetMemory函数的形式参数,只在函数内部有效,等函数返回之后,动态开辟内存尚未释放,并且无法找到,所以造成内存泄漏。

要改进怎么改进呢?我们需要用到二级指针,将str地址传进去即可。

void GetMemory(char **p){
    *p=(char*) malloc(100);
}
void Test(void){
    char *str=NULL;
    //传递str的地
    GetMemory(&str);
    strcpy(str,"hello world");
    printf(str);
    //释放空间
    free(str);
    str=NULL;
}
int main(){
    Test();
    return 0;
}

或者:如果不想用二级指针可以把申请好空间的地址返回去

char* GetMemory(char *p){

    p=(char*) malloc(100);
    return p;
}
void Test(void){
    char *str=NULL;
   str= GetMemory(str);
    strcpy(str,"hello world");
    printf(str);
    free(str);
    str=NULL;
}
int main(){
    Test();
    return 0;
}


输出结果:

C语言-动态内存管理(三)_内存泄漏_04


推荐阅读