gpt4 book ai didi

c - strncpy导致段错误

转载 作者:太空狗 更新时间:2023-10-29 16:58:55 25 4
gpt4 key购买 nike

我只是在用strncpy弄乱。

我的程序看起来像这样

typedef struct
{
char from_str[10];
}test;

main ()
{

test s1;
memset(&s1,0,sizeof(test));
char src[10]="himansh";
char dest[10];

memset(dest,0,10);
src[3]='\0';

printf("src is %s and strlen is %d \n",
src,strlen(src));

fflush(stdout);

strncpy(s1.from_str,src,100);

printf("s1.from_str is %s , src is %s \n",
s1.from_str,src);
return 1;

}

在执行strncpy之前,我在“src”字符串中添加了一个“\0”字符,“src”字符串的长度变为3,目标数组的大小为10。但是在strncpy中,我将要复制的字节数设置为100 。

这意味着我的源字符串以NULL终止。现在,像任何字符串函数一样,strncpy应该尝试仅复制3个字节,即使我提供的字节数大于3(在本例中为100)。它做到了,但我也遇到了段错误。

我的结果如下所示
src is him and strlen is 3
s1.from_str is him , src is him
Segmentation fault (core dumped)

为什么在这里发生段错误。

有人可以帮我从这里出去吗。

最佳答案

我可以指出您的手册页,网站等,但是最终重要的是C标准本身。作为标准运行时库的一部分,用法和行为在C99-§7.23.2.4中定义为:

#include <string.h>
char *strncpy(char * restrict s1,
const char * restrict s2,
size_t n);

Description The strncpy function copies not more than n characters (characters that follow a null character are not copied) from the array pointed to by s2 to the array pointed to by s1. If copying takes place between objects that overlap, the behavior is undefined. If the array pointed to by s2 is a string that is shorter than n characters, null characters are appended to the copy in the array pointed to by s1, until n characters in all have been written.

Returns The strncpy function returns the value of s1.



这里有很多隐含的信息,最重要的是:如果源字符串长度(不包括其空字符终止符)达到或超过了指定的目标缓冲区长度,则 strncpy()而不是终止目标字符串。

此外,尽管在标准中有明确规定(请参见上文),但它仍然使我感到困惑,有多少工程师不知道 strncpy()用空字符尾填充目标字符串缓冲区,直到当源字符串长度较小时达到指定长度 n为止比目标缓冲区的大小大。得出以下不可避免的结论:

strncpy() API将始终将n字符写入目标缓冲区引用的地址。

在您的情况下,由于目标缓冲区只有10个字符宽,因此您将在可写内存的定义端之后再写入90个字符,从而进入 未定义行为的领域。

此时,您必须问自己“那有什么用?”有一个基本的用例。它使您可以将多达 n字符复制到目标缓冲区,并具有可预测性,因为您知道自己不会超出 n字符。时期。但最终,您需要一个以空值结尾的字符串,因此正确的用法是这样的:
char dst[ N ]; 
strncpy(dst, src, N-1);
dst[N-1] = 0;

其中 Ndst缓冲区的硬长度,以char为单位,并且大于或等于 1。注意 dst可能也是动态分配的内存指针:
char *dst = malloc( N * sizeof(char) ); 
strncpy(dst, src, N-1);
dst[N-1] = 0;

有了上述内容,您将在 dst处始终有一个以空值终止的字符串。如果源字符串长度小于指定的目标缓冲区长度,则 strncpy()将用空字符尾部填充其余缓冲区,直到源字符复制+尾部填充空字符总数等于 n,最后声明是多余的。如果源字符串的长度等于或大于目标缓冲区的长度,则到达 strncpy()字符后, N-1将停止复制,并且final语句在缓冲区的末尾设置一个空字符。这将导致原始源的“缩减”前缀字符串,但是最重要的是,它可以确保您不会在以后扫描终止符的字符串API调用中超出目标缓冲区的边界。

上述技术的实用性始终值得商bat。我是C++专家,所以 std::string可以使我免于这种疯狂。但是现实是这样的:有时您会关心 src是否未完全复制到 dst;有时候你不知道。有用之处在于 视情况而定。对于在UI中显示字符串数据,这(可能)无关紧要。对于复制要用于关键数据的字符串,局部前缀-子字符串将是 Not Acceptable 。当警察向“小约瑟夫·约翰逊”签发逮捕证时,将有一些解释要做,当他的父亲(“约瑟夫·约翰逊”)被送进 jail 时,因为签发证件软件的名称缓冲区只能容纳15个字符。

综上所述,您的段错误归结为以下语句:
strncpy(s1.from_str,src, 100); // length parameter is wrong.

回顾上面的粗体语句: strncpy()总是将n字符写入目标缓冲区引用的地址。” 。这意味着上述代码将 始终写入100个字符到目标缓冲区,在您的情况下,该缓冲区只有10个字符,因此行为不确定,并且可能是 ker-boom

如果目标缓冲区是固定长度的字符数组,请执行以下操作纠正此问题:
strncpy(s1.from_str,src, sizeof(s1.from_str)/sizeof(s1.from_str[0])-1);
s1.from_str[ sizeof(s1.from_str)/sizeof(s1.from_str[0])-1 ] = 0;

有关如何对长度为N个字符的动态字符串执行此操作,请参见先前的用法。

关于c - strncpy导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14065391/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com