静态全局变量vs全局变量C
我有下面的程序。如果我声明变量a、b、c为静态全局变量,它会给出分段错误,但如果我声明它们为非静态全局变量或局部变量,它不会给出分段错误。为什么它会有这样的行为?我知道变量所能存储的数据太多了,但为什么只有声明的静态数据时它才会给出seg错误呢?静态声明的变量是否存储在堆栈框架中不允许覆盖的不同部分 编辑:我知道strcpy不安全。但这不是我的问题。我想了解为什么一个溢出会给出segfault,为什么另一个溢出可能不会给出segfault静态全局变量vs全局变量C,c,stack-overflow,stack-frame,C,Stack Overflow,Stack Frame,我有下面的程序。如果我声明变量a、b、c为静态全局变量,它会给出分段错误,但如果我声明它们为非静态全局变量或局部变量,它不会给出分段错误。为什么它会有这样的行为?我知道变量所能存储的数据太多了,但为什么只有声明的静态数据时它才会给出seg错误呢?静态声明的变量是否存储在堆栈框架中不允许覆盖的不同部分 编辑:我知道strcpy不安全。但这不是我的问题。我想了解为什么一个溢出会给出segfault,为什么另一个溢出可能不会给出segfault #include<stdio.h> #inc
#include<stdio.h>
#include<string.h>
static char a[16];
static char b[16];
static char c[32];
int main(int argc, char *argv[]){
// char a[16];
//char b[16];
//char c[32];
strcpy(a,"0123456789abcdef");
strcpy(b,"0123456789abcdef");
strcpy(c,a);
strcpy(c,b);
printf("a = %s\n",a);
return 0;
}
#包括
#包括
静态字符a[16];
静态字符b[16];
静态字符c[32];
int main(int argc,char*argv[]){
//chara[16];
//charb[16];
//charc[32];
strcpy(a,“0123456789abcdef”);
strcpy(b,“0123456789abcdef”);
strcpy(c,a);
strcpy(c,b);
printf(“a=%s\n”,a);
返回0;
}
注意C中的const char*字符串始终以0结尾,这意味着字符串“0123456789abcdef”实际上是17个字符:“0123456789abcdef\0”
我建议您始终使用安全版本
strncpy()
您还可以查看文档,它明确地告诉您包含空字符
堆栈变量中的内存对齐很重要。 尝试使用-fstack-protector-strong或类似的堆栈保护选项,您将看到崩溃。 在c之后声明一个int并使数组c溢出,您可以看到崩溃。 你需要确保没有填充物。 因为b是一个数组,所以从“a”溢出的任何内容都会进入b。 尝试以下方法:
struct foo {
char c[10];
int x;
} __attribute__((packed));
当您溢出c时,您将看到崩溃
溢出时会遇到未定义的行为。当写入超过缓冲区结尾时,会写入任意内存,而该内存可能具有未定义的行为。这就是所谓的未定义行为。不要问一些未定义的问题。奇怪的是,只有当它们是静态的时,才会发生崩溃,因为静态和非静态全局变量之间的差异应该只是范围问题。(当然,根据C语言,这是允许的行为,它说任何事情都可能发生)我怀疑您的编译器确实以不同的方式将静态全局变量分配给非静态全局变量,因此在C结束后不久恰好有一个0字节,但是当它们不是静态的时候就没有了。访问缓冲区之外的内存是未定义的行为。因为这是未定义的行为,所以任何事情都可能发生。任何东西因此,有时该行为是seg故障事件。有时,它是一些隐藏的东西,会破坏堆栈调用链等其他数据。有时它是良性的。永远不要期望有某种行为。应始终避免此类未定义的行为。当某些数据损坏时,成本可能会非常高,如果应用程序以seg故障事件结束,用户将非常不满意。
strncpy
不安全,在这种情况下没有帮助。很少有情况下,strncpy
是正确的函数use@slux83谢谢你。我知道,但我的问题是,当它不是静态的时候,为什么不给出一个segfault,它不会给出一个未定义的行为。如果你的程序没有那么短的话,它也可能会出错。堆栈损坏的问题是,发现崩溃的时间是不可预测的。@Matt使用strncpy始终是一个很好的做法,因为您限制了指定缓冲区大小的副本,以防在某些情况下丢失空字符reason@slux83不,这是个坏习惯。在这种情况下使用strncpy
仍会导致缓冲区溢出(尽管排序不同),因为strncpy不为null,在字符串不适合时终止字符串。此处没有任何堆栈变量。只需创建一个struct foo f;