c - 为什么保存受限指针的值不会给出未定义的行为?
问题描述
我正在对虚拟机进行编程,并且我已将受限指针联合起来以迭代脚本的指令流:
union Pointer {
uint8_t *restrict UInt8Ptr;
uint16_t *restrict UInt16Ptr;
uint32_t *restrict UInt32Ptr;
uint64_t *restrict UInt64Ptr;
int8_t *restrict Int8Ptr;
int16_t *restrict Int16Ptr;
int32_t *restrict Int32Ptr;
int64_t *restrict Int64Ptr;
float *restrict FloatPtr;
double *restrict DoublePtr;
const char *restrict CStrPtr;
void *restrict Ptr;
};
对于 CALL 操作码,我保存了指令指针的值(间接地),如果我理解“restrict”关键字的用法,会导致未定义的行为。
(--regs[regStk].SelfPtr)->Ptr = ip.Ptr; /* push rip */
*--regs[regStk].SelfPtr = regs[regBase]; /* push rbp */
regs[regBase] = regs[regStk]; /* mov rbp, rsp */
我还应该说,在 RET 操作码中,指令指针的值被恢复了。
regs[regStk] = regs[regBase]; /* mov rsp, rbp */
regs[regBase] = *regs[regStk].SelfPtr++; /* pop rbp */
ip.Ptr = (*regs[regStk].SelfPtr++).Ptr; /* pop rip */
我已经做了很多测试,甚至使用了不同的编译器(GCC 和 clang v3.5 和 clang v6.0),这似乎并没有产生未定义的行为,这是为什么呢?
编辑更新:
这些变量都被声明为一个局部块范围:
int32_t VM_Exec(struct VM *const restrict vm)
{
if( !vm or !vm->CurrScript.Ptr ) {
return ErrInstrBounds;
}
union Value *const restrict regs = vm->Regs; // <--
union Pointer pc = (union Pointer){.UInt8Ptr = regs[regInstr].UCharPtr}; // <--
解决方案
只有在更高级别的优化时才考虑限制关键字。仅限 gcc -O2 和 -O3。
在您的示例中,我没有看到任何可能导致问题的东西,因为我们不知道这些数组是如何声明的以及如何使用的。
在这里你有一个例子 - 我打破了与编译器的合同。
unsigned p = 100;
void foo1(void)
{
p++;
}
void foo(unsigned *restrict x)
{
printf("p = %u\n", *x);
foo1();
printf("p = %u\n", *x);
}
int main()
{
foo(&p);
}
结果是(-O3)
100
100
用 -O1 编译
100
101
另一个例子:-O3
unsigned p = 100;
void foo1(void)
{
p++;
}
void foo(unsigned *restrict x)
{
unsigned *restrict p1;
p1 = x;
printf("p = %u\n", *x);
foo1();
printf("p = %u\n", *x);
*p1++;
printf("p = %u\n", *x);
}
int main()
{
foo(&p);
}
结果:
p = 100
p = 100
p = 101
推荐阅读
- javascript - 单击 x 可编辑和空 td
- cordova - 如何将 Cordova 服务脚本设置为使用 http 而不是 https?
- python - 如何让 terraform 在 Kali Linux 上使用 runcmd?
- azure - 多次出现 count.index 的 Azure 多区域部署错误
- javascript - 使用 Nodejs 运行时连接 mongoDb 中的多个数据库
- firebase - 使用 Firebase SDK 处理错误代码
- python - Windows 上的 Python Tkinter?
- data-binding - 附加属性绑定不适用于 Flayout(Xaml、UWP)
- javascript - 材料表可编辑:使所有行一次可编辑
- python - Python:使用预设图形和布局与多个绘图一起使用