首页 > 解决方案 > 缺少堆栈更新

问题描述

我正在尝试深入了解堆栈分配,因此我打算获得这样的堆栈配置:

0x000009 -> 0,
0x000005 -> 1,
0x000001 -> 2,
...

这是代码:

int main(){

    int i;
    int j;
    int pseudoarray;

    printf("address of i \t\t%p\n",&i);
    printf("address of j \t\t%p\n",&j);
    printf("address of pseudoarray \t%p\n\n",&pseudoarray);

    for(i =0;i<10;i++){

        *((&pseudoarray)-i)=i;
        printf("Written at \t%p value \t%d\n\n",(&pseudoarray)-i, i);

        for(j =0; j<10;j++){
            printf("Read at \t%p value \t%d\n",(&pseudoarray-j), *((&pseudoarray-j)));
        }
        printf("\n\n\n");
    }

    printf("\n%d times done",i);

    return 0;
}

然而它只写到第三个单元格,然后什么也不写。

这是它打印的内容(从第 6 次写入操作到 10 的打印与 5 相同):

C:\Users\Halib\OneDrive\Documents\Corsi\Corso C>plain.exe
address of i            0061FF1C
address of j            0061FF18
address of pseudoarray  0061FF14

Written at      0061FF14 value  0

Read at         0061FF14 value  0         <-- wrote a 0 here
Read at         0061FF10 value  4200912
Read at         0061FF0C value  4201019
Read at         0061FF08 value  4201019
Read at         0061FF04 value  6422280
Read at         0061FF00 value  4214946
Read at         0061FEFC value  4199673
Read at         0061FEF8 value  6422312
Read at         0061FEF4 value  -2
Read at         0061FEF0 value  157728263



Written at      0061FF10 value  1

Read at         0061FF14 value  0
Read at         0061FF10 value  1         <-- wrote a 1 here
Read at         0061FF0C value  4201019
Read at         0061FF08 value  4201019
Read at         0061FF04 value  6422280
Read at         0061FF00 value  4214946
Read at         0061FEFC value  4199673
Read at         0061FEF8 value  6422312
Read at         0061FEF4 value  -2
Read at         0061FEF0 value  157728263



Written at      0061FF0C value  2

Read at         0061FF14 value  0
Read at         0061FF10 value  1
Read at         0061FF0C value  2
Read at         0061FF08 value  2
Read at         0061FF04 value  6422280
Read at         0061FF00 value  4214946
Read at         0061FEFC value  4199673
Read at         0061FEF8 value  6422312
Read at         0061FEF4 value  -2
Read at         0061FEF0 value  157728263



Written at      0061FF08 value  3

Read at         0061FF14 value  0
Read at         0061FF10 value  1
Read at         0061FF0C value  2
Read at         0061FF08 value  2          <-- I expected 3 here
Read at         0061FF04 value  6422280
Read at         0061FF00 value  4214946
Read at         0061FEFC value  4199673
Read at         0061FEF8 value  6422312
Read at         0061FEF4 value  -2
Read at         0061FEF0 value  157728263



Written at      0061FF04 value  4

Read at         0061FF14 value  0
Read at         0061FF10 value  1
Read at         0061FF0C value  2
Read at         0061FF08 value  2
Read at         0061FF04 value  6422280    <-- expected 4 here
Read at         0061FF00 value  4214946
Read at         0061FEFC value  4199673
Read at         0061FEF8 value  6422312
Read at         0061FEF4 value  -2
Read at         0061FEF0 value  157728263



Written at      0061FF00 value  5

Read at         0061FF14 value  0
Read at         0061FF10 value  1
Read at         0061FF0C value  2
Read at         0061FF08 value  2
Read at         0061FF04 value  6422280
Read at         0061FF00 value  4214946
Read at         0061FEFC value  4199673
Read at         0061FEF8 value  6422312
Read at         0061FEF4 value  -2
Read at         0061FEF0 value  157728263

编辑:

代码修改:尝试:

int i;
int j;
int pseudoarray;

printf("address of i \t\t%p\n",&i);
printf("address of j \t\t%p\n",&j);
printf("address of pseudoarray \t%p\n\n",&pseudoarray);


for(i =0;i<10;i++){

    *((&pseudoarray)+i)=i;
}

    printf("\n\n");

for(j =0; j<10;j++){
        printf("Read at \t%p value \t%d\n",(&pseudoarray+j), *((&pseudoarray+j)));
    }

return 0;

产生以下输出:

address of i            0061FF1C
address of j            0061FF18
address of pseudoarray  0061FF14



Read at         0061FF14 value  0
Read at         0061FF10 value  1
Read at         0061FF0C value  2
Read at         0061FF08 value  2
Read at         0061FF04 value  6422280
Read at         0061FF00 value  4214921
Read at         0061FEFC value  4199645
Read at         0061FEF8 value  6422312
Read at         0061FEF4 value  -2
Read at         0061FEF0 value  -498040528

有人可以帮我吗?非常感谢。

标签: cpointersstack

解决方案


写作并没有停止工作,但是您打印值的方式正在破坏它们。假设您的堆栈指针通常位于 0061FF08。当您在内部循环中调用 printf() 时,它将发出类似于以下内容的代码:

...
      push  %r0   / assume it computed *(&pseudoarray-j) int r0
      push  %r1   /  assume it computed &pseudoarray-1 into r1
      push  %r3   /  fmt string
      call  printf
      add   $12, %sp
 ....

因此,这只是重写了您的一些伪数组 [-j] 条目,因为几乎普遍堆栈都会增长。由于 ABI 更喜欢某些堆栈对齐方式,这很复杂,因此您只需几句话就可以摆脱它,但是一旦您摆脱它,您就完成了。

如果你想引起一些真正的混乱,不要从伪数组中减去,添加它,这样你就会覆盖你所在函数的调用帧的位。顺便说一下,这就是缓冲区溢出和类似机制劫持程序的方式. ps:当编译器为程序分配堆栈空间时,它通常会在顶部附近发出这样的序列:

func:
    push  %frame     / save the frame pointer register
    mov   %sp, %frame  / save the stack end pointer.
    sub   $num, %sp    / this allocates space for local vars.

并返回:

mov  %frame, %sp
pop  %frame
ret

所以在函数的代码生成部分,可以自由地发出如下序列:

push   %r0
call   tolower
add    $4, %sp

它修改堆栈,并允许tolower构造自己的堆栈帧。当前堆栈指针下方的堆栈内存可能暂时可用,但很难与编译器同步。如果你想尝试一下:

void play() {
   int    save[10];
   int    i;
   int    temp;
   for (i = 0; i < 10; i++) {
         (&temp)[-i] = 1 << i;
   }
   for (i = 0; i < 10; i++) {
          save[i] = (&temp)[-i];
   }
   for (i = 0; i < 10; i++) {
          printf("%d vs %d\n", save[i], (&temp)[-i]);
   }
}

笔记:

  1. 这不是真正的 C。#UB 人看到这个时会闪现邪恶的眼睛并喷出胡言乱语。
  2. 在某种程度上这不会产生一致的结果,并且是一种糟糕的编程方式,他们是正确的。
  3. 这就是发现,这是对编译器的有效使用。
  4. 您可能必须使用 -O0、-std=c90 等咒语仔细调整编译器选项,以使其正常运行。

推荐阅读