为什么返回的堆栈指针被 gcc 替换为空指针?
Why is a returned stack-pointer replaced by a null-pointer by gcc?
我在 c 中创建了以下函数作为 demonstration/small 关于堆栈在 c 中如何工作的谜语:
#include "stdio.h"
int* func(int i)
{
int j = 3;
j += i;
return &j;
}
int main()
{
int *tmp = func(4);
printf("%d\n", *tmp);
func(5);
printf("%d\n", *tmp);
}
这显然是未定义的行为,编译器也会对此发出警告。然而不幸的是,编译并没有完全成功。由于某种原因,gcc 将返回的指针替换为 NULL
(参见第 6d6 行)。
00000000000006aa <func>:
6aa: 55 push %rbp
6ab: 48 89 e5 mov %rsp,%rbp
6ae: 48 83 ec 20 sub [=11=]x20,%rsp
6b2: 89 7d ec mov %edi,-0x14(%rbp)
6b5: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
6bc: 00 00
6be: 48 89 45 f8 mov %rax,-0x8(%rbp)
6c2: 31 c0 xor %eax,%eax
6c4: c7 45 f4 03 00 00 00 movl [=11=]x3,-0xc(%rbp)
6cb: 8b 55 f4 mov -0xc(%rbp),%edx
6ce: 8b 45 ec mov -0x14(%rbp),%eax
6d1: 01 d0 add %edx,%eax
6d3: 89 45 f4 mov %eax,-0xc(%rbp)
6d6: b8 00 00 00 00 mov [=11=]x0,%eax
6db: 48 8b 4d f8 mov -0x8(%rbp),%rcx
6df: 64 48 33 0c 25 28 00 xor %fs:0x28,%rcx
6e6: 00 00
6e8: 74 05 je 6ef <func+0x45>
6ea: e8 81 fe ff ff callq 570 <__stack_chk_fail@plt>
6ef: c9 leaveq
6f0: c3 retq
这是用 gcc 版本 7.5.0 和 -O0
-flag 编译的二进制文件的反汇编;没有使用其他标志。这种行为使整个代码毫无意义,因为它应该显示堆栈在函数调用中的行为方式。有什么方法可以使用至少是最新版本的 gcc 来更直接地编译此代码?
出于好奇:首先像这样更改代码的行为有什么意义?
将 return 值放入指针变量似乎会改变编译器的行为,它会生成 return 指向堆栈的指针的汇编代码:
int* func(int i) {
int j = 3;
j += i;
int *p = &j;
return p;
}
我在 c 中创建了以下函数作为 demonstration/small 关于堆栈在 c 中如何工作的谜语:
#include "stdio.h"
int* func(int i)
{
int j = 3;
j += i;
return &j;
}
int main()
{
int *tmp = func(4);
printf("%d\n", *tmp);
func(5);
printf("%d\n", *tmp);
}
这显然是未定义的行为,编译器也会对此发出警告。然而不幸的是,编译并没有完全成功。由于某种原因,gcc 将返回的指针替换为 NULL
(参见第 6d6 行)。
00000000000006aa <func>:
6aa: 55 push %rbp
6ab: 48 89 e5 mov %rsp,%rbp
6ae: 48 83 ec 20 sub [=11=]x20,%rsp
6b2: 89 7d ec mov %edi,-0x14(%rbp)
6b5: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
6bc: 00 00
6be: 48 89 45 f8 mov %rax,-0x8(%rbp)
6c2: 31 c0 xor %eax,%eax
6c4: c7 45 f4 03 00 00 00 movl [=11=]x3,-0xc(%rbp)
6cb: 8b 55 f4 mov -0xc(%rbp),%edx
6ce: 8b 45 ec mov -0x14(%rbp),%eax
6d1: 01 d0 add %edx,%eax
6d3: 89 45 f4 mov %eax,-0xc(%rbp)
6d6: b8 00 00 00 00 mov [=11=]x0,%eax
6db: 48 8b 4d f8 mov -0x8(%rbp),%rcx
6df: 64 48 33 0c 25 28 00 xor %fs:0x28,%rcx
6e6: 00 00
6e8: 74 05 je 6ef <func+0x45>
6ea: e8 81 fe ff ff callq 570 <__stack_chk_fail@plt>
6ef: c9 leaveq
6f0: c3 retq
这是用 gcc 版本 7.5.0 和 -O0
-flag 编译的二进制文件的反汇编;没有使用其他标志。这种行为使整个代码毫无意义,因为它应该显示堆栈在函数调用中的行为方式。有什么方法可以使用至少是最新版本的 gcc 来更直接地编译此代码?
出于好奇:首先像这样更改代码的行为有什么意义?
将 return 值放入指针变量似乎会改变编译器的行为,它会生成 return 指向堆栈的指针的汇编代码:
int* func(int i) {
int j = 3;
j += i;
int *p = &j;
return p;
}