C语言 使用 strncpy 时堆栈和堆的奇怪行为



我发现了一个非常有趣的问题。

当我使用以下代码时:

int main() {
    char * in = "hi, ";
    char str[10];
    strncpy(str, in, 2);
    printf("output = %s", str);
    return 0;
}

我的结果什么都没有,printf不起作用。

但是如果我使用它:

int main() {
    char * in = "hi, ";
    char * str = malloc(sizeof(char) * 10) ;
    strncpy(str, in, 2);
    printf("output = %s", str);
    return 0;
}

我可以得到我所期望的。

为什么会这样?是因为堆栈和堆吗?这究竟是如何产生这种巨大差异的?

这两种情况下,问题都是您的字符串在调用 strncpy 后无法正确终止。

指定复制2个字符,并且源字符串in的长度为 4。因此,strncpy将复制 2 个字符,并且由于该字符小于源字符串的长度,因此不会添加空终止符 - 要了解为什么会这样,请查看 strncpy 的文档:

If count is reached before the entire string src was copied, the resulting character array is not null-terminated.

在这种情况下,您需要:

str[2] = '';

在"strncpy"之后。

第二种情况似乎有效,因为您从malloc获得的缓冲区恰好初始化为所有零,但您不应该依赖它。

请查看 strncpy 的文档,注意空终止的例外情况,一般来说,要小心字符串终止!

有关更多详细信息,请参阅:为什么C++中的字符串通常以"\0"结尾?

代码编译良好。运行时错误可能是因为您尚未以 null 终止str

从手册页:

strncpy() 函数类似,除了最多 n 个字节 复制 SRC。 警告:如果前 n 个中没有空字节 字节的 src,放置在 dest 中的字符串将 不以空值终止。

strncpy()后添加str[2]=0;

您可以使用零初始化内存以使其处于"安全"状态。

看看下面的代码,

int main() {
    char * in = "hi, ";
    char str[10]={0};    
    strncpy(str, in, 2);
    printf("output = %s", str);
    return 0;
}
int main() {
    char * in = "hi, ";
    char * str = calloc(10,sizeof(char));
    strncpy(str, in, 2);
    printf("output = %s", str);
    free(str);      //<<Important step
    return 0;
}

str[2] = '';也是一个有效的解决方案。

相关内容

  • 没有找到相关文章

最新更新