gpt4 book ai didi

c - 有没有一种安全的方法来指定一个对象的值可能因为从未使用过而未初始化?

转载 作者:太空狗 更新时间:2023-10-29 15:17:24 24 4
gpt4 key购买 nike

免责声明:以下纯属学术问题;我将此代码与任何生产系统保持至少 100 m 的距离。这里提出的问题是无法在任何“现实生活”案例中衡量的。

考虑以下代码 ( godbolt link ):

#include <stdlib.h>

typedef int (*func_t)(int *ptr); // functions must conform to this interface

extern int uses_the_ptr(int *ptr);
extern int doesnt_use_the_ptr(int *ptr);

int foo() {
// actual selection is complex, there are multiple functions,
// but I know `func` will point to a function that doesn't use the argument
func_t func = doesnt_use_the_ptr;

int *unused_ptr_arg = NULL; // I pay a zeroing (e.g. `xor reg reg`) in every compiler
int *unused_ptr_arg; // UB, gcc zeroes (thanks for saving me from myself, gcc), clang doesn't
int *unused_ptr_arg __attribute__((__unused__)); // Neither zeroing, nor UB, this is what I want

return (*func)(unused_ptr_arg);
}

编译器没有合理的方法知道 unused_ptr_arg 是不需要的(因此归零是浪费时间),但我知道,所以我想通知编译器 unused_ptr_arg 可以有任何值,例如寄存器中用于将其传递给 func 的任何值。

有没有办法做到这一点?我知道我超出了标准,所以我可以接受特定于编译器的扩展(尤其是 gcc 和 clang)。

最佳答案

使用 GCC/Clang `asm` 构造

在 GCC 和 Clang 以及其他支持 GCC 扩展汇编语法的编译器中,您可以这样做:

int *unused_ptr_arg;
__asm__("" : "=x" (unused_ptr_arg));

return (*func)(unused_ptr_arg);

__asm__ 构造 says “这里是一些汇编代码,此时要插入到程序中。它会将结果写入 unused_ptr_arg 中您选择的任何位置。” (x 约束意味着编译器可以选择内存、处理器寄存器或机器支持的任何其他内容。)但实际的汇编代码是空的 ("")。所以没有生成汇编代码,但是编译器认为unused_ptr_arg已经被初始化了。在用于 x86-64 的 Clang 6.0.0 和 GCC 7.3(目前在 Compiler Explorer 中的最新版本)中,这会生成一个没有 xorjmp

使用标准 C

考虑一下:

int *unused_ptr_arg;
(void) &unused_ptr_arg;

return (*func)(unused_ptr_arg);

(void) &unused_ptr_arg; 的目的是获取 unused_ptr_arg 的地址,即使该地址未被使用。这将禁用 C 2011 [N1570] 6.3.2.1 2 中的规则,该规则表示如果程序使用本可以通过 register 声明的具有自动存储持续时间的未初始化对象的值,则行为未定义。因为它的地址被占用了,它不能用register声明,因此根据这个规则使用这个值不再是未定义的行为。

因此,该对象具有不确定的值。然后是指针是否可能具有陷阱表示的问题。如果指针在所使用的 C 实现中没有陷阱表示,则不会因为仅引用该值而发生陷阱,就像将其作为参数传递时一样。

result with Clang 6.0.0 at Compiler Explorer是没有设置参数寄存器的 jmp 指令,即使 -Wall -Werror 添加到编译器选项。相反,如果删除 (void) 行,则会导致编译器错误。

关于c - 有没有一种安全的方法来指定一个对象的值可能因为从未使用过而未初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50020196/

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