以下文章来源于编程珠玑 ,作者守望先生

    

近期文章

貌似很久没有更新文章了,前两天更新了一篇《想后台运行没想到导致磁盘满了》,里面涉及的内容比较广,可惜看的人不多。今天来看到小题,复习一下。


下面的输出结果是什么?为什么

//来源:公众号编程珠玑
//作者:守望先生
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void getmemory(char *p) {
    p=(char *) malloc(128);
    strcpy(p,"hello 编程珠玑");
}
int main( ) {
    char *str = NULL;
    getmemory(str);
    printf("%s\n",str);
    free(str);
    return 0;
}

结果

先不要看下面的分析,上面的代码中,你发现了哪些问题呢?

这是一道非常常见的面试题,很多人一眼看过去就知道问题在哪了,是的,程序运行异常,可能出现Segmentation fault。

分析

首先第一个问题在于,str的值是没有变的,也就是说执行getmemory之后,str还是NULL,即不能达到预期,使得str指向一个保存着字符串的内存区域。而这里主要考察的是对C语言中参数值传递的理解。更加详细的解释可以参考《函数参数的传值和传指针有什么区别?》。

而真正导致Segmentation fault的原因是printf中,str是NULL,而访问NULL位置的内存是非法的。这一点在《解引用NULL为什么会导致程序挂死?》中也有解释。

另外使用strcpy进行字符串的拷贝也是不推荐的,可能有缓冲区溢出的风险,推荐使用strncpy。关于缓冲区溢出,可以参考《C语言入坑指南-缓冲区溢出》。

修正

//来源:公众号编程珠玑
//作者:守望先生
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void getmemory(char **p) {
    *p = (char *) malloc(128);
    if(NULL == *p){
        printf("get memory failed\n");
        return;
    }
    strncpy(*p,"hello 编程珠玑",sizeof("hello 编程珠玑"));
}
int main( ) {
    char *str = NULL;
    getmemory(&str);
    if(NULL != str){
        printf("%s\n",str);
    }
    free(str);
    str = NULL;
    return 0;
}



作者:守望,Linux应用开发者,目前在公众号【编程珠玑】 分享Linux/C/C++/数据结构与算法/工具等原创技术文章和学习资源。