首页 > 试题广场 >

如下程序用于输出“Welcome to Huawei Tes

[不定项选择题]
如下程序用于输出“Welcome to Huawei Test”,请指出其中潜在风险的位置()
char * GetWelcome(void){
    char * pcWelcome;
    char * pcNewWelcome;
    pcWelcome = "Welcome to Huawei Test";
    pcNewWelcome = (char *)malloc(strlen(pcWelcome));    //1
    if(NULL == pcNewWelcome){
        return NULL;        //2
    }
    strcpy(pcNewWelcome, pcWelcome);    //3
    return pcNewWelcome;            //4
}
printf("%s\n", GetWelcome());

  • 1
  • 2
  • 3
  • 4
咋感觉都没说明白呢。
1处,难道只有我一个人看出来正确形式是:pcNewWelcome=(char*)malloc(strlen(pcWelcome)*sizeof(char)) ,当然形式上对了。
但是逻辑上呢?strlen()统计字符个数,不含结尾符'\0',所以这样子分配会少一个字节。
3处,由1处,既然新分配的空间少了一个字节,你用原来的来复制到新的里?能装下吗?不能。
完。
编辑于 2016-07-31 17:14:45 回复(11)

我发现评论区都分析错了或不透彻,下面是我的分析:

1、3是错的,但严格来说只是1错了,如果1改正过来,3自然也就对了。这个是大家的共识,但1错在哪,就没人说正确了。

先看下题目程序的运行结果:


咋一看没什么问题,其实是有很大BUG的。那就是分配的空间只能22位,而pcWelcome复制过来应该占23位,因为后面还有'\0'。所以复制过来的‘\0’会超出pcNewWelcome的范围,向后覆盖了一个字节。这个可是会造成未知错误的重大隐患。另外,如果紧跟的那一个字节不是'\0',而是其它内容,那你打印pcNewWelcome的时候,就会发现这个字符串后面莫明多了很多其它字符。比如,“abcdefg”这个字符紧跟着pcNewWelcome分配的22个字节空间,那么你打印pcNewWelcome的结果是:Welcome to Huawei Testabcdefg,打印到有'\0'的地方才停止。
怎么改呢?
有人说,把strlen改成sizeof,这个错得就更离谱了。pcWelcome是指针变量,用sizeof求出的大小就是这个变量占有的空间,就是4byte,而不是字符串占的空间。当然了,改成sizeof后在这个“小”程序中运行结果也看不出什么问题。但是pcWelcome的23字节内容复制过来放在只有4字节的pcNewWelcome后,会向后覆盖19个字节,这就相当恐怖了。这种BUG很隐蔽,会导致一些莫名其妙的问题出现,而且你不太容易找到根本原因。

所以,只要把第一句改成pcNewWelcome=(char*)malloc(strlen(pcWelcome)+1);即可,这样就可以分配23个字节了,pcWelcome的内容复制过来刚刚好。

编辑于 2019-07-06 16:10:54 回复(2)
我想问的是  如果把1改对了  那3还用改吗  这种出题方式本身就有问题
发表于 2016-10-04 13:44:20 回复(2)
第一处:malloc动态分配的内存是在堆上的,需要进行free()函数释放,这里假设是分配正确的,这样第四处就可以认为是正确的,因为它还没有释放。 第二处:可以认为是在strcpy函数执行前的自检测,如果为NULL,由实现者决定其返回值,一般为NULL。 第三处:strcpy函数的功能是把从src地址开始且含有'\0'结束符的字符串复制到以dest开始的地址空间。但是在第一处进行动态分配内存的时候使用的是strlen而不是sizeof,这样就少了'\0'结束符,不能正确进行复制操作。 因此,第一处和第三处是错误的。
发表于 2016-03-12 14:13:08 回复(11)
4是对的吗?不是说不能在函数中返回函数中声明的指针?这个指针在函数退出以后会被释放。
发表于 2015-08-05 10:14:46 回复(10)
个人认为真正的错误只有第三处。
发表于 2016-03-04 14:14:58 回复(1)
       牛友答案:@JustDoIt.cpp
       1处错误,pcNewWelcome=(char*)malloc(strlen(pcWelcome))中strlen()统计字符个数,不含结尾符‘\0’,分配内存时就会少一个字节,正确形式是pcNewWelcome=(char *)malloc(strlen(pcWelcome)*sizeof(char));
       3处错误, strcpy函数的功能是把从src地址开始且含有'\0'结束符的字符串复制到以dest开始的地址空间, 但是在第一处进行动态分配内存的时候使用的是strlen而不是sizeof,这样就少了'\0'结束符,不能正确进行复制操作。

编辑于 2017-04-10 21:57:14 回复(3)
这道题有问题, 我不理解它在考什么?
首先说测试结果,直接用题中代码编译是没有问题的。

输出结果:
这里大家对1的错误基本上是肯定的,因为它少了一个字节,有可能出现未知后果。这里并不是说pcNewWelcome的输出会出现未知后果,而是说在pcNewWelcome假设恰好也有一个有用的内存时,strcpy会那个地址进行操作,从而产生未知后果。
但对答案里的第4个,函数的返回值是值传递的,应该不存在销毁不销毁的问题。所以我不认为哪错了。
编辑于 2016-01-28 10:57:06 回复(2)
第1处错误,需要pcNewWelcome=(char*)malloc(strlen(pcWelcome)+1);
if语句中应该将两个语句调换位置

发表于 2015-07-01 16:57:42 回复(0)
在给pcNewWelcome分配内存的地方,strlen(pcWelcome)只计算了字符串长度,并没有给'\0',也就是空字符预留一个字节的空间,所以在复制字符串到pcNewWelcome的时候,可能会发生缓冲区溢出。应该将语句1改为: ```c pcNewWelcome = (char *)malloc(strlen(pcWelcome) + 1); ``` 这样可以在分配内存时多预留一个字节的空间来存放 '\0' 字符。这样就能保证复制字符串时不会溢出。
发表于 2023-08-16 12:15:49 回复(0)
这题的逻辑……日了狗
发表于 2019-11-06 23:22:20 回复(0)
首先内存地址没有分配够,所以后面的拷贝操作也会出错。因为strlen不会将结尾标识'\0'计入,所以导致内存分配相较实际少了一个字节,而在strcpy时会将所有字符串拷贝,包括'\0'。故错误的地方为1、3.
发表于 2017-09-28 16:33:58 回复(0)
1错误strlen应该改为sizeof;2是参数的检查,正确;3因为1的错误,所以三错;4,有人可能会认为局部变量会被自动释放,但是题中的变量是有malloc分配的内存空间,不会被自动释放,所以4也正确。
发表于 2016-06-23 00:18:30 回复(1)
四不是可以编译通过的吗?求解释。。。
发表于 2015-11-04 22:02:07 回复(0)
4是错的吧,返回栈上分配的指针,函数结束后,该指针无效。。。 而2中,已经判断是NULL,证明其分配失败了,为何还要free 所以我觉得答案是AD
发表于 2015-10-08 16:58:35 回复(4)
2不能说是错误吧,已经是NULL还需要free吗
发表于 2015-04-25 21:35:47 回复(0)
首先,1是错的 ,应该是strlen(pcWelcome)+1
2 是对的,
3 由于 strlen(pcWelcome)+1改了之后 , pcNewWelcome所指的空间可以放下pcWelcome所指的内容了,也是对的
4 pcNewWelcome指针是在函数内部定义的,在栈上分配的,函数调用结束后,会释放它的内容  这个应该是对的
编辑于 2016-02-19 19:47:29 回复(6)
  1. pcNewWelcome = (char *)malloc(strlen(pcWelcome));//1 这里的风险是,malloc分配的内存大小应该包括字符串的结束字符 '\0',但是strlen(pcWelcome)只计算了字符串的长度,没有包括 '\0'。因此,分配的内存可能不足以存储整个字符串,包括结束字符。

  2. if(NULL == pcNewWelcome){ return NULL; }//2 这里的风险是,如果malloc返回NULL(即内存分配失败),函数会返回NULL。但是,如果调用GetWelcome函数的代码没有检查返回值是否为NULL,它可能会尝试使用一个空指针,从而导致程序崩溃。

  3. strcpy(pcNewWelcome, pcWelcome);//3 这里的风险是,由于pcNewWelcome分配的内存可能不足以存储整个字符串,包括结束字符,strcpy可能会越界写入,导致未定义行为,比如程序崩溃或者数据损坏。

  4. return pcNewWelcome;//4 这里的风险是,pcNewWelcome是在函数内部分配的,当函数返回时,分配的内存并没有被释放,也没有被传递给调用者,这会导致内存泄漏。此外,返回的指针在函数结束后就不再有效,因为局部变量pcNewWelcome的生命周期结束了,但是返回值却被用作有效的内存地址,这可能会导致悬挂指针问题。

发表于 2024-10-17 20:28:46 回复(0)
第二个指针占22位,而第一个占23位
编辑于 2024-03-16 21:58:47 回复(0)
strlen不算结尾的\0,所以在拷贝的时候会有问题
编辑于 2024-03-05 15:12:20 回复(0)