我有两个问题。
第一个问题。为什么以下代码实际上在mac上工作(用gcc编译)?
int main()
{
int *p;
*p = 1;
return 0;
}
当拆卸线'* p = 1;'时变
mov rax, [rbp - 16]
mov qword [rax], 1
第二个问题。什么位于[rbp - 16]?
在问这个问题时我将操作数[rbp - 16]解释为[rbp + 16],这显然没有意义。我累了......
你回答我的问题。
答案 0 :(得分:3)
您的代码有undefined behaviour。这意味着允许它做任何事情都是允许的。它不必崩溃。
当你的程序启动时,有一些代码在main()
之前执行并且使用相同的堆栈。你的盒子上可能发生的事情是包含p
的堆栈区域之前已被另一个保留有效指针的函数使用。你的main()
偶然偶然发现了指针,已经取消引用它,并且正在腐蚀别人的记忆。
我尝试使用gcc
编译代码并在OSX上运行它,但它确实崩溃了。
答案 1 :(得分:1)
我记得,如果没有明确指定其值,C中的变量会被先前用户在堆栈上留下的某些值初始化。所以,这个值绝对是 random ,而你的代码只是改变了随机存储区的值。如果你得到空指针,你的程序将失败。
答案 2 :(得分:0)
其他人已经充分涵盖了这种行为的不确定性。您的具体问题似乎是了解拆卸。这是一个有点冗长,但希望有用的演练:
第一条指示:mov rax, [rbp - 16]
RBP是“基指针寄存器”。这将地址保存在当前堆栈帧的内存中。正如评论者指出的那样,rbp - 16
是当前堆栈框架中p
的位置。它将是一个8字节的指针。如果您在int *q;
之后立即声明了另一个本地变量p
,那么它的地址可能会在rbp - 24
。在这种情况下,RAX是通用寄存器。这会将8字节指针从位于rbp - 16
堆栈的位置复制到RAX中。正如其他人所指出的那样,由于你没有初始化p
,rbp - 16
的值是内存中最后一个使用该内存的东西,或者是完全随机的东西。方括号括号表示操作数rbp - 16
是指针,并且应复制地址rbp - 16
处的内存内容,而不是表达式rbp - 16
的字面结果。您可以将rbp - 16
表达式视为具有int**
类型。
第二条指令:mov qword [rax], 1
QWORD是“四字”的缩写。历史上,一个字节是一个字节,“字”是两个字节,“长”或“双字”(对于“双字”)是四个字节,当然,“四字”是8个字节。该指令将文字1(扩展为其八字节形式)复制到RAX指向的位置。方括号括号表示操作数RAX是一个指针,并且该文字将被操作数复制到指向的位置。如果指令是mov qword rax, 1
,则将文字1(以其八字节形式)复制到RAX中。
正如其他人所说的那样,因为那个指针是垃圾(偶然发生在内存中),这种情况很好(但不能保证)会崩溃。