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

标签 c++ llvm llvm-clang

我有以下代码

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/

相关文章:

c++ - 理解 C++ 中的引用和拷贝的问题

java - JVM中包含哪些功能

llvm - 有没有办法知道在LLVM中使用alloca指令创建的堆栈分配局部变量的堆栈地址

c++ - 使用来自另一个 channel 的 channel 时出现 LLVM 错误

c++ - Clang AST用于模板类的模板方法

clang - 如何通过CLANG只检查一个检查器?

c++ - STL排序比较类函数

c++ - cin 在我的代码中不起作用

c++ - 为什么结构体的 sizeof 不等于每个成员的 sizeof 之和?

c - 在未使用的符号上获取 SEGFAULT