Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
导致分段错误的strncpy_C_Segmentation Fault_Strncpy - Fatal编程技术网

导致分段错误的strncpy

导致分段错误的strncpy,c,segmentation-fault,strncpy,C,Segmentation Fault,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

我只是在胡闹

我的程序是这样的

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)
为什么分割错误会发生在这里

有人能帮我吗。

请看:

stpncpy()和strncpy()函数最多从s2复制n个字符 进入s1。如果s2的长度小于n个字符,则s1的剩余部分为 用“\0”字符填充。否则,s1不终止

剩下的就填了

因此:

char*strncpy(char*destination,const char*source,size\u t num );

复制字符串中的字符复制源的第一个num字符 去目的地。如果源C字符串的结尾(这是有信号的 在复制num个字符之前找到, 目标用零填充,直到总共包含num个字符 我已经写信给它了

因此,尽管源字符串长度小于目标缓冲区大小,但由于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 
或者最好编写一个
\u countof

#define _countof(s) (sizeof(s)/sizeof(s[0]))
................
strncpy(s1.from_str,src,_countof(s1.from_str) - 1);
strncpy(s1.from_str,src,100)

为什么在函数中使用
100
,from_str和src都分配了10个连续的字节,但您正在复制100个字节,这将导致seg。过失

像这样使用,


strncpy(s1.from_str,src,10)

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

#include <string.h>
char *strncpy(char * restrict s1,
      const char * restrict s2,
      size_t n);
其中
N
dst
缓冲区的硬长度,单位为字符,大于或等于
1
。请注意,
dst
也可以是动态分配的内存指针:

char *dst = malloc( N * sizeof(char) ); 
strncpy(dst, src, N-1);
dst[N-1] = 0;
使用上述方法,您将始终在
dst
处有一个以null结尾的字符串。如果源字符串长度小于指定的目标缓冲区长度,
strncpy()
将使用空字符尾部填充缓冲区的其余部分,直到复制的源字符+尾部填充的空字符总数等于
n
,并且最终语句是多余的。如果源字符串长度等于或大于目标缓冲区长度,
strncpy()
将在达到
N-1
字符后停止复制,并且final语句在缓冲区末尾设置空字符。这将导致原始源的前缀字符串“缩减”,但最重要的是,它确保您不会使用稍后扫描终止符的字符串API调用超出目标缓冲区的边界

上述技术的实用性总是有争议的。我是C++的家伙,所以<代码> STD::String 从这些疯狂中拯救我快乐的自我。但现实是这样的:有时你关心
src
是否没有完整地复制到
dst
;有时候你不会。有用性取决于情景。对于在UI中显示字符串数据,这(可能)无关紧要。对于复制用于关键数据的字符串,不接受部分前缀子字符串。当警方向“小约瑟夫·约翰逊”发出逮捕令时,当他的父亲(“约瑟夫·约翰逊”)被关进监狱时,会有一些解释,因为逮捕令发布软件的名称缓冲区仅包含15个字符

综上所述,您的细分错误归结为以下陈述:

strncpy(s1.from_str,src, 100); // length parameter is wrong.
回想一下上面的粗体语句:
strncpy()
将始终向目标缓冲区引用的地址写入
n
字符。”
。这意味着上面的代码将始终向目标缓冲区写入100个字符,在您的情况下,目标缓冲区只有10个字符宽,因此行为未定义,很可能

如果目标缓冲区是固定长度字符数组,请执行以下操作以纠正此问题:

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个字符的动态字符串执行此操作。

但此处src字符串的大小小于dest字符串的大小,而N大于src和dest字符串的大小。@icepack,因为from_str之后的90个字节(内存可能不属于您)被覆盖。然后它取决于编译器设置/OS。。。发生的事情是正确的,但答案没有具体说明这一切,它只是参考文献的一个副本,我只是在瞎混。这是在LINUX机器上发生的,但我在另一台UNIX机器上没有遇到任何seg故障。您认为它应该尝试做什么,以及它做什么是两件完全不同的事情。此seg故障发生在一台LINUX机器上,但不会发生在另一台UNIX机器上。为什么会这样?@HimanshuGupta:超出分配内存的写入是一种未定义的行为(UB),分段错误是众多UBs中的一个@HimanshuGupta:如果答案有帮助,请尝试投票并接受错误answer@HimanshuGupta当前位置在引擎盖下发生的事情是,strncpy在复制位置之后的任何内容上都进行了写入。这可能取决于您定义的变量,编译器如何在内存中布局数据,如果它删除了一些变量,因为它知道它们不存在
strncpy(s1.from_str,src, 100); // length parameter is wrong.
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;