【发布时间】:2014-10-11 10:19:11
【问题描述】:
我有以下代码
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 之后 memcpy,以便在输出流中我看到地址来自vtable_old 而不是 vtable_new!这发生在 -O3 甚至 -O2 上。如果我取消注释第一个输出,一切都会恢复正常。
这是什么 - 预期的行为,clang 中的错误还是我遗漏了什么?如何解决?
编辑
将volatile 添加到vtable_new 声明
void ** volatile vtable_new = ((void ***)newr)[0];
帮助。 -fno-strict-aliasing 和 asm volatile ("" : : : "memory") 屏障没有。我还是不明白编译器在这里做了什么。
【问题讨论】:
-
要调试奇怪的问题,您确实需要发布 MCVE,否则我们只是猜测。
-
以及别名冲突,写入
vtable_new会在很多方面导致UB(你似乎试图摆弄一个对象的vtable) -
@MattMcNabb 是的,这就是我必须做的(修改 vtable)。
标签: c++ llvm llvm-clang