gpt4 book ai didi

c - 在 C 中从堆栈中复制数据

转载 作者:太空狗 更新时间:2023-10-29 11:31:21 28 4
gpt4 key购买 nike

我正在为我的几个 friend 整理一个 C 谜语,当一个 friend 提请我注意以下片段(恰好是我一直在写的谜语的一部分)时) 在 OSX 上编译和运行时运行不同

#include <stdio.h>
#include <string.h>

int main()
{
int a = 10;
volatile int b = 20;
volatile int c = 30;

int data[3];

memcpy(&data, &a, sizeof(data));

printf("%d %d %d\n", data[0], data[1], data[2]);
}

您期望的输出是 10 20 30Linux 下恰好是这种情况,但是当代码是在 OSX 下构建的,您会得到 10 后跟两个随机数。在调试并查看编译器生成的 assembly 之后,我得出结论,这是由于堆栈的构建方式所致。我绝不是 assembly 专家,但是在 Linux 上生成的汇编代码似乎很容易理解,而在 OSX 上生成的代码让我很困惑关闭一点。也许我可以从这里得到一些帮助。

这是在 Linux 上生成的代码:

        .file   "code.c"
.section .text.unlikely,"ax",@progbits
.LCOLDB0:
.section .text.startup,"ax",@progbits
.LHOTB0:
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB23:
.cfi_startproc
movl $10, -12(%rsp)
xorl %eax, %eax
movl $20, -8(%rsp)
movl $30, -4(%rsp)
ret
.cfi_endproc
.LFE23:
.size main, .-main
.section .text.unlikely
.LCOLDE0:
.section .text.startup
.LHOTE0:
.ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609"
.section .note.GNU-stack,"",@progbits

这是在 OSX 上生成的代码:

        .section        __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 12
.globl _main
.p2align 4, 0x90
_main: ## @main
.cfi_startproc
## BB#0:
pushq %rbp
Ltmp0:
.cfi_def_cfa_offset 16
Ltmp1:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp2:
.cfi_def_cfa_register %rbp
subq $16, %rsp
movl $20, -8(%rbp)
movl $30, -4(%rbp)
leaq L_.str(%rip), %rdi
movl $10, %esi
xorl %eax, %eax
callq _printf
xorl %eax, %eax
addq $16, %rsp
popq %rbp
retq
.cfi_endproc

.section __TEXT,__cstring,cstring_literals
L_.str: ## @.str
.asciz "%d %d %d\n"


.subsections_via_symbols

我真的只对这里的两个问题感兴趣。

  1. Why is this happening?

  2. Are there any get-arounds to this issue?

我知道这不是利用堆栈的实用方法,因为我是一名专业的 C 开发人员,这确实是我发现这个问题很有趣并投入一些时间的唯一原因。

最佳答案

访问声明变量末尾之后的内存是未定义的行为——无法保证当您尝试这样做时会发生什么。由于编译器在 Linux 下生成程序集的方式,您碰巧直接在堆栈的一行中获取了 3 个变量,但是这种行为只是巧合 - 编译器可以合法地在堆栈变量之间添加额外数据,或者实际上做任何事情——结果不是由语言标准定义的。所以在回答你的第一个问题时,它正在发生,因为你正在做的不是设计语言的一部分。在回答你的第二个问题时,没有办法从多个编译器可靠地获得相同的结果,因为编译器没有被编程为可靠地重现未定义的行为。

关于c - 在 C 中从堆栈中复制数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45340497/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com