【问题标题】:Character array in C(Puts vs printf)C中的字符数组(Puts vs printf)
【发布时间】:2013-10-20 02:53:43
【问题描述】:

我对 C 中的字符数组有一些疑问,我有一个大小为 1 的字符数组,逻辑上说当我输入超过 2 个字符时,我应该遇到分段错误,但是 puts 正确打印出数组而printf 打印数组的某些部分以及垃圾值,为什么会发生这种情况

#include<stdio.h>
int main()
{
int i;
char A[1];
printf("%d\n",(int)sizeof(A));
gets(A);
puts(A);
for(i=0;i<8;i++)
{
printf("%c\n",A[i]);
}
}

O/P:

1
abcdefg
abcdefg
a




f
g

为此,我必须在程序中输入多个array size 字符以引发分段错误。是因为堆栈中的 SFP 吗? SFP的大小是4个字节,如有错误请指正

1
abcdefghijklmnop
abcdefghijklmnop
a




f
g
h
Segmentation fault

【问题讨论】:

  • 写入无效内存会产生未定义的行为......这意味着结果不一定直观也不一致。有些事情似乎有效或部分有效——但如果你依赖它,通常不会;)
  • 我明白,但是puts 似乎每次在上述程序中都能始终如一地工作。
  • “似乎始终如一地工作”和“始终如一地工作”之间存在巨大差距。当仅在当前程序的范围内查看它时,它很可能会一直持续工作——无论是细微的变化(移动变量定义、将代码从堆栈上的一个例程移动到另一个例程、更改为新的编译器、使用不同的编译器进行编译) flags) 有可能破坏事物。

标签: c printf character-arrays puts


【解决方案1】:
  1. 其实即使只写一个字符,还是缓冲区溢出,因为gets()会写一个空字符到数组中。
  2. 缓冲区溢出不一定意味着分段错误。您不能以任何方式依赖未定义的行为。可能程序只是用了几次才打破了它不应该写入的内存。

看来你已经知道gets()很危险,应该避免,我加了这个以防万一。

【讨论】:

  • 我正在尝试为作业实现堆栈粉碎攻击,但是我编写的程序实现了一个函数调用和gets 函数中的输入,gets 不是段错误直到我输入大约 8 * 数组大小。为了进一步理解我写了上面这段代码的问题
  • @user2433145 是的,主要思想是你不能依赖未定义的行为来工作,你也不能依赖它不工作。
【解决方案2】:

好的,其他人用高级语言和长辈的经验解释了。

我想解释一下你在组装层的情况。

你知道为什么你的第一个情况没有意外吗?

因为您的缓冲区溢出不会破坏其他进程的内存,所以操作系统不会向您的进程发出分段错误信号。

为什么你的堆栈长度大于数组的大小?

因为对齐。许多操作系统需要一个对齐 x 字节的堆栈帧来实现高效寻址。

x 取决于机器。

例如,如果 x 是 16 个字节。

char s[1] will lead the stack to 16 byte; 
char s[17] will lead the stack to 32byte.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-21
    • 2011-01-28
    • 1970-01-01
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-29
    相关资源
    最近更新 更多