C 字符串的数组内存分配
我已经使用数组分配方法编写了简单的字符串程序。我已经为字符数组分配了10个字节,但当我给出输入时,程序正在接受大于10个字节的输入字符串。只有当我给出大约21个字符的输入字符串时,我才会出现分段错误。当我的输入超过分配的数组限制时,为什么没有分段错误 节目: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:
#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标准中删除的原因。