gpt4 book ai didi

c++ - LLVM-clang 编译器优化器以一种非常奇怪的方式重新排列代码,怎么办?

转载 作者:太空宇宙 更新时间:2023-11-04 13:45:13 34 4
gpt4 key购买 nike

我有以下代码

renderer_opengl *oldr = (renderer_opengl*)enabler->renderer;
renderer *newr = new renderer;

void **vtable_old = ((void ***)oldr)[0];
void **vtable_new = ((void ***)newr)[0];

...

void *draw_new = vtable_new[IDX_draw];
void *reshape_gl_new = vtable_new[IDX_reshape_gl];
void *update_tile_new = vtable_new[IDX_update_tile];

// out << draw_new << std::endl;

p.verifyAccess(vtable_new, sizeof(void*)*32, true);
memcpy(vtable_new, vtable_old, sizeof(void*)*32);

out << draw_new << std::endl;

vtable_new[IDX_draw] = draw_new;
...

编译

Apple LLVM version 6.0 (clang-600.0.51) (based on LLVM 3.5svn)

我在这里做什么并不重要,但问题是编译器重新排列代码并将赋值给 draw_new after memcpy ,所以在输出流中我看到的地址来自 vtable_old 而不是 vtable_new!这发生在 -O3 甚至 -O2 上。如果我取消注释第一个输出,一切都会恢复正常。

这是什么 - 预期的行为,clang 中的错误还是我遗漏了什么?如何解决?

编辑

volatile 添加到 vtable_new 声明

void ** volatile vtable_new = ((void ***)newr)[0];

有帮助。 -fno-strict-aliasingasm volatile (""::::"memory") 屏障没有。我仍然不明白编译器在这里做什么。

最佳答案

正如其他人所提到的,我认为编译器正在利用严格的别名规则。尝试替换:

void **vtable_old = ((void ***)oldr)[0];
void **vtable_new = ((void ***)newr)[0];

与:

void **vtable_old;
void **vtable_new;

memcpy( &vtable_old, oldr, sizeof(vtable_old));
memcpy( &vtable_new, newr, sizeof(vtable_new));

关于c++ - LLVM-clang 编译器优化器以一种非常奇怪的方式重新排列代码,怎么办?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26313588/

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