我只是与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]=' ';
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中,我已经将字节数为be复制为100。
这意味着我的源字符串被终止。现在,即使我提供的字节数超过3(在这种情况下为100),也应该像任何字符串函数一样尝试仅复制3个字节。它这样做了,但是我也得到了分割错误。
我的结果如下所示
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);
描述
strncpy
函数从指向s2指向的数组到指向by的数组的 CC_1函数不超过n个字符(未复制null字符的字符) S1。如果在重叠的对象之间进行复制,则行为是不确定的。 如果S2指向的数组比n个字符短,则将null字符附加到S1指向的数组中的副本上,直到编写所有字符。返回
strncpy
函数返回S1的值。
在这里有重要的暗示信息,最重要的是: strncpy()
will not 如果源字符串长度(不包括其null),则用null字符串终止目标字符串字符终结器)满足或超过指定的目标缓冲区长度)。
n
。这得出了以下不可避免的结论:
strncpy()
API始终将n
字符写入目标缓冲区引用的地址。
在您的情况下,由于目标缓冲器只有10颗克宽,因此您正在编写90个字符,超过了可写入的记忆的定义结束,因此走进了未定义的行为的土地。
在这一点上,您必须问自己"那么什么用?"是可以说的基本用例。它使您可以将n
字符副本复制到目标缓冲区,并且可以可预测您不会超越n
字符。时期。最终,您想要一个零终止的字符串,所以适当的用法是:
char dst[ N ];
strncpy(dst, src, N-1);
dst[N-1] = 0;
N
是char中dst
缓冲液的硬长度,与1
相当于或相等。请注意,dst
可能仅仅是一个动态分配的内存指针:
char *dst = malloc( N * sizeof(char) );
strncpy(dst, src, N-1);
dst[N-1] = 0;
使用上述内容,您将始终在dst
上具有一个null终止的字符串。如果源字符串长度小于指定的目标缓冲区长度,则strncpy()
将用无效的字符尾部填充其余的缓冲区,直到总计源型 尾部 尾巴填充的无效 - 字符等于n
,最终语句是多余的。如果源字符串长度等于或大于目标缓冲区长度,则一旦达到N-1
字符,strncpy()
将停止复制,并且最终语句在缓冲区的末端设置了无效字符。这会导致原始源的"切下"前缀字符串,但最重要的是,它可以确保您不会使用以后的字符串 - API调用来扫描终止器的字符串缓冲区的边界。
上述技术的有用性始终值得商bat。我是C 的家伙,所以std::string
从所有这些精神错乱中保存了我的幸福自我。但是现实是这样:有时您会在乎src
是否在其全部中都没有复制到dst
;有时候你没有。有用性是非常情况取决于情况。对于在UI中呈现string-data,这可能不会(可能)。要复制一个用于关键数据的字符串,部分前提是substring将是不可接受的。当警察向"小约瑟夫·约翰逊(Joseph Johnson Jr.。
所有话都说,您的细分错误取决于此说法:
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 chars的动态字符串。
来自http://www.cplusplus.com/reference/cstring/cstring/strncpy/
char * strncpy(char *目的地,const char * source,size_t num num );
从字符串复制字符复制源的第一个数字字符 到达目的地。如果源C字符串的末端(发出信号 在复制数字字符之前找到了零字符) 目的地用零填充,直到数字总数为 被写成。
因此,尽管源字符串长度小于目标缓冲区大小的大小,但是由于strncpy的传递行为,它试图覆盖其余字符以外的目标缓冲区大小,从而导致分段故障
而不是复制超过100个字符的大小应等于目标缓冲区中的最大允许大小,因此,您可以书面
strncpy(s1.from_str,src,sizeof(s1.from_str)/sizeof(s1.from_str[0]) - 1); Actual size -1 to accomodate the null terminator
或更好地编写_countof
宏
#define _countof(s) (sizeof(s)/sizeof(s[0]))
................
strncpy(s1.from_str,src,_countof(s1.from_str) - 1);
请参阅:http://www.manpagez.com/man/3/strncpy/
stpncpy()和strncpy()函数在s2中大多数n个字符复制 进入S1。如果S2小于N字符长,则S1的其余部分为 充满" 0"字符。否则,S1不会终止。
其余部分填充....
so:
strncpy( s1.from_str, src, 10 );
strncpy(s1.from_str,src,100);
为什么您在功能中使用100
,From_str和SRC都有10个连续分配的字节,但是您正在复制100个字节,这将导致SEG。故障。
这样使用,
strncpy(s1.from_str,src,10);