Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.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
C 字符串的数组内存分配_C_String_Undefined Behavior_Buffer Overflow_Gets - Fatal编程技术网

C 字符串的数组内存分配

C 字符串的数组内存分配,c,string,undefined-behavior,buffer-overflow,gets,C,String,Undefined Behavior,Buffer Overflow,Gets,我已经使用数组分配方法编写了简单的字符串程序。我已经为字符数组分配了10个字节,但当我给出输入时,程序正在接受大于10个字节的输入字符串。只有当我给出大约21个字符的输入字符串时,我才会出现分段错误。当我的输入超过分配的数组限制时,为什么没有分段错误 节目: #include <stdio.h> #include <string.h> void main() { char str[10]; printf ("\n Enter the string:

我已经使用数组分配方法编写了简单的字符串程序。我已经为字符数组分配了10个字节,但当我给出输入时,程序正在接受大于10个字节的输入字符串。只有当我给出大约21个字符的输入字符串时,我才会出现分段错误。当我的输入超过分配的数组限制时,为什么没有分段错误

节目:

#include <stdio.h>
#include <string.h>

void main() {

    char str[10];

    printf ("\n Enter the string: ");
    gets (str);
    printf ("\n The value of string=%s",str);
    int str_len;
    str_len = strlen (str);
    printf ("\n Length of String=%d\n",str_len);


}
#包括
#包括
void main(){
char-str[10];
printf(“\n输入字符串:”);
获取(str);
printf(“\n字符串的值=%s”,str);
int str_len;
str_len=strlen(str);
printf(“\n字符串长度=%d\n”,str\u len);
}
输出:

输入字符串:n durga prasad

string=n durga prasad的值
字符串长度=14


如您所见,字符串长度显示为14,但我只分配了10个字节。长度怎么可能超过我分配的大小?

请不要使用
get()
它会遇到缓冲区溢出问题,而缓冲区溢出又会调用

当我的输入超过分配的数组限制时,为什么没有分段错误

一旦您的输入超过分配的数组大小(即,9个有效字符+1个空终止符),立即对数组位置的下一次访问将变为非法并调用UB。分割错误是UB的副作用之一,它不是必须的


解决方案:改为使用。

当您输入的字符数超过数组可以容纳的字符数时,则表示您有未定义的行为。您的数组可以容纳9个字符,后面跟一个空终止符,因此此数组中的任何贬值都是UB

不要使用
gets()
而是使用
fgets()

char a[10];
fgets(a,sizeof(a),stdin);
通过使用
fgets()
可以避免缓冲区溢出问题和未定义的行为


PS:
fgets()
在声明数组时带有换行符,如
char str[10],编译器不会始终精确分配所需的字节数。它通常分配更多,如果您是在64位系统中,通常是8的倍数,例如,在您的情况下可能是16

所以,即使你要求10个字节,你也可以操纵更多。但当然,这是非常不值得推荐的,因为正如你所说的,它会产生分割错误


而且,正如Sourav和Gopi的其他回答所说,使用而不是可能有助于产生较少的未定义行为。

正如您已经知道的,您的输入会导致缓冲区溢出,我不打算重复原因。相反,我想回答一个特别的问题

  • “当我的输入超过分配的数组限制时,为什么没有分段错误?”
可能存在或不存在分段错误的原因取决于一种称为。一旦超出分配的内存边界,就肯定不会出现分段错误。相反,您将面临的是UB(如前所述)。现在,引用UB的结果

[…]调用未定义行为的程序可能编译和运行,并产生正确的结果,或不可检测的错误结果,或任何其他行为

因此,在访问下一个内存时,不一定会立即出现分段错误。它可能运行得很好,除非它到达某些特定进程实际上无法访问的内存,然后,SIGSEV信号(11)将被触发


但是,在运行到UB之后,无法验证任何后续语句的任何输出。因此,
strlen()
的输出在这里无效。

请阅读。没有任何东西可以阻止您在超出分配内存限制的情况下进行写入,但这会导致糟糕的事情发生。哦,这就是为什么
get
函数多年来一直被废弃,甚至从最新的C标准中删除的原因。