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



这里有很多隐含的信息,最重要的是:如果源字符串长度(不包括其空字符终止符)达到或超过了指定的目标缓冲区长度,则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/

10-14 09:55