C- strncpy导致分割故障



我只是与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);

相关内容

  • 没有找到相关文章

最新更新