我试图深入研究堆栈分配,所以我打算获得这样的堆栈配置:
0x000009 -> 0,
0x000005 -> 1,
0x000001 -> 2,
...
Run Code Online (Sandbox Code Playgroud)
这是代码:
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;
}
Run Code Online (Sandbox Code Playgroud)
但是,它只写入第三个单元,然后不写入任何内容。
这是它打印的内容(从第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
Run Code Online (Sandbox Code Playgroud)
编辑:
代码修改:尝试:
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;
Run Code Online (Sandbox Code Playgroud)
产生以下输出:
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
Run Code Online (Sandbox Code Playgroud)
有人可以帮我吗?非常感谢。
编写工作尚未停止,但是您打印值的方式正在破坏它们。假定您的堆栈指针通常位于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
....
Run Code Online (Sandbox Code Playgroud)
因此,这几乎覆盖了您的某些伪数组[-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.
Run Code Online (Sandbox Code Playgroud)
并返回:
mov %frame, %sp
pop %frame
ret
Run Code Online (Sandbox Code Playgroud)
因此在函数的代码生成部分,它可以自由发出如下序列:
push %r0
call tolower
add $4, %sp
Run Code Online (Sandbox Code Playgroud)
修改堆栈,并允许lower构造自己的堆栈框架。当前堆栈指针下方的堆栈内存可能暂时可用,但是很难将其与编译器同步。如果您想尝试一下:
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]);
}
}
Run Code Online (Sandbox Code Playgroud)
笔记: