运维开发网
广告位招商联系QQ:123077622
 
广告位招商联系QQ:123077622

我在这里擦除堆栈吗?

运维开发网 https://www.qedev.com 2020-07-05 15:18 出处:网络
我正在 Linux上使用gcc,下面的代码编译成功,但没有正确打印变量i的值,如果一次输入一次字符我跳转或减少到0.我知道我在scanf使用%d作为字符(我试图擦除堆栈).这是一个尝试擦除堆栈或其他东西的情况吗?(我想如果堆
我正在 Linux上使用gcc,下面的代码编译成功,但没有正确打印变量i的值,如果一次输入一次字符我跳转或减少到0.我知道我在scanf使用%d作为字符(我试图擦除堆栈).这是一个尝试擦除堆栈或其他东西的情况吗?(我想如果堆栈被删除,程序将崩溃).

#include <stdio.h>

int main()
{
    int i;
    char c;

    for (i=0; i<5; i++) {
        scanf ("%d", &c);
        printf ("%d ", i);
    }
    return 0;
}
除了main的参数之外,堆栈上还有一个int和一个char.

假设sizeof(int)== 4并且只看一下i和c.

(              int i               )(char c )
[   0   ][   1   ][   2   ][ 3 (&i)][ 4 (&c)]

所以这实际上是没有argc和* argv的堆栈布局.

在这种情况下,我消耗的内存是c的四倍.

堆栈以相反的方向增长,所以如果你写一个大于char的东西到c,它会写入[4]并进一步向左,从不向右.所以[5]永远不会被写入.相反,你覆盖[3].

对于你写一个int到c和int比c大四倍的情况,你实际上写到[1] [2] [3] [4],只是[0]不会被覆盖,但是3 / int的4个内存将被破坏.

在大端系统中,i的最高有效字节将存储在[3]中,因此会被此操作覆盖.在小端系统上,最重要的字节存储在[0]中并将被保留.尽管如此,你以这种方式破坏你的筹码.

正如艾姆斯提到的那样并非总是如此.可能存在不同的效率对齐,或者因为平台仅支持对齐访问,因此在变量之间留下间隙.此外,只要编译器没有as-if规则所述的可见副作用,就允许编译器进行任何优化.在这种情况下,变量可以完美地存储在寄存器中,并且永远不会保存在堆栈中.但是许多其他编译器优化和平台依赖性可能使这种方式变得更加复杂.所以这只是最简单的情况,不考虑平台依赖性和编译器优化,也似乎是在你的特殊情况下会发生的一些细微差别.

扫码领视频副本.gif

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号