【发布时间】:2015-12-11 16:17:22
【问题描述】:
背景:我经常处理二进制数据,而且我经常需要处理原始指针。我也经常需要大小,以便我可以检查我是否读/写了边界(合理,对吗?)。现在我正在尝试为包含基础数据大小的指针创建一个语法糖类,以便我可以简化函数声明。
问题演示 - 我的课程背后的崩溃代码可以简化为:
char *a = (char*) malloc(4); // some underlying data
strncpy(a, "1234", 4); // that is not statically linked so it can be written to
uint32_t *ptr = reinterpret_cast<uint32_t*>(a);
ptr[0] = 1234; // works
reinterpret_cast<int&>(ptr[0]) = 1234; // curiously, this works too
*reinterpret_cast<int*>(ptr[0]) = 1234; // this crashes the program
printf("%d\n", ptr[0]);
上述程序崩溃,如 cmets 中所述。 Valgrind 输出如下:
Invalid write of size 4
at 0x40064A: main (in /home/rr-/test)
Address 0x4d2 is not stack'd, malloc'd or (recently) free'd
我怀疑我违反了严格的别名规则,但是:
- 我确保使用
char*作为底层结构。很可能,这并不重要,因为我的reinterpret_casting 不是char*,而是uint32_t*,编译器并不关心uint32_t*最初指向的内容。 - 但即使我使用
-fno-strict-aliasing和-fstrict-aliasing,程序仍然崩溃...(我在 GNU/Linux 下使用 g++ 5.2.0 编译程序。)
谁能告诉我哪里出错了,我该如何纠正这个问题?
【问题讨论】:
-
你认为
*reinterpret_cast<int*>(ptr[0]) = 1234;会做什么? -
是的,我在上下班途中意识到了这一点。多么愚蠢的错误。
标签: c++ crash strict-aliasing