Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 函数从字符串复制到已分配内存时出错_C_Memcpy_Strlen_Calloc - Fatal编程技术网

C 函数从字符串复制到已分配内存时出错

C 函数从字符串复制到已分配内存时出错,c,memcpy,strlen,calloc,C,Memcpy,Strlen,Calloc,对于下面的C字谜问题,我有一些新的想法。我很好奇更多的C程序员会怎么想。。。请查看示例代码: char * strdup (const char * s) { char * buf; int len; assert(s != NULL); len = strlen(s); buf = (char *) calloc(len + 1, sizeof(char)); memcpy(buf, s, len); return buf; }

对于下面的C字谜问题,我有一些新的想法。我很好奇更多的C程序员会怎么想。。。请查看示例代码:

char * strdup (const char * s) { 
    char * buf;
    int len;
    assert(s != NULL);
    len = strlen(s);
    buf = (char *) calloc(len + 1, sizeof(char)); 
    memcpy(buf, s, len); 
    return buf;
}
上面建议的strdup()实现包含一个运行时错误,该错误可能不会在每次调用时一致出现。以下哪项准确描述了此错误

这一问题的可能答案是:

1 calloc()的参数不会导致分配足够的内存来存储s的内容

2如果内存不足,calloc()可能会失败并返回NULL。该代码没有预料到这种情况

3 memcpy()如果用于复制ASCII字符串,可能会损坏数据

4 buf从不以NUL结尾,因此不能由影响字符串的C库函数使用

5该函数返回指向动态内存的指针。应避免这种做法,并始终构成内存泄漏

我认为正确答案是2,但更多的是因为其他答案对我来说似乎不正确,而不是因为答案2是直接正确的答案

  • 答案1似乎不正确,因为calloc保留了足够的内存(len+1)来适当结束字符串

  • 我不知道答案3写了什么

  • 回答4:memcpy将s的内容复制到buf,最后一个字节等于0(复制len字节,注意previos对calloc的调用将最后一个字节填充为0)。所以这个答案是不正确的,

  • 答复5:

你觉得怎么样?
提前感谢…

正确答案是2和5

#2
,因为内存分配函数可能会失败,您必须检查它们的返回值

#5
因为,除非记录函数动态分配返回缓冲区的事实,否则调用者无法知道必须释放返回缓冲区

#1
是不正确的,因为正如您正确地说的
calloc
分配字符串所需的内存+为
NULL
终止所需的额外字节

#3
不正确,因为它不正确,
memcpy
只是将数据从源复制到目标。它不受内存中存储内容的影响


#4
不正确,因为
calloc
会将分配的内存归零。

我的答案也是2。因为
calloc
在失败时会返回NULL,您永远不应该使用NULL指针调用
memcpy
。1和4完全不正确。不知道3“memcpy()如果用于复制ASCII字符串,可能会损坏数据”是什么意思。5可能是有争议的,但是在C中没有太多的选择!strlen返回一个size\u t,但len是int?顺便说一句,为什么不使用strcpy?我认为5不正确,只是因为“总是”这个词。@lerosQ:我认为它是正确的,因为除非您的接口文档说明了动态内存分配,否则这样做“总是”不正确。由于没有提到文件,我认为这是一个有效的声明。是的,#5中的措辞听起来像是你应该始终避免动态内存分配。@MrLister:除非你告诉用户你的函数,或者更好的选择是让用户预先分配缓冲区并将其作为参数传递。如果你有自由设计自己的接口,第二个选择总是更好。在我的书中,如果你有一个“除非”,那么就没有“总是”的位置。但无论如何,这种做法应该避免。