【发布时间】:2017-03-06 16:35:33
【问题描述】:
我在这样的代码中有总线错误:
char* mem_original;
int int_var = 987411;
mem_original = new char [250];
memcpy(&mem_original[250-sizeof(int)], &int_var, sizeof(int));
...
const unsigned char* mem_u_const = (unsigned char*)mem_original;
...
const unsigned char *location = mem_u_const + 250 - sizeof(int);
std::cout << "sizeof(int) = " << sizeof(int) << std::endl;//it's printed out as 4
std::cout << "byte 0 = " << int(*location) << std::endl;
std::cout << "byte 1 = " << int(*(location+1)) << std::endl;
std::cout << "byte 2 = " << int(*(location+2)) << std::endl;
std::cout << "byte 3 = " << int(*(location+3)) << std::endl;
int original_var = *((const int*)location);
std::cout << "original_var = " << original_var << std::endl;
几次效果都很好,打印出来:
sizeof(int) = 4
byte 0 = 0
byte 1 = 15
byte 2 = 17
byte 3 = 19
original_var = 987411
然后它失败了:
sizeof(int) = 4
byte 0 = 0
byte 1 = 15
byte 2 = 17
byte 3 = 19
Bus Error
它在 Solaris OS (C++ 5.12) 上构建和运行 Linux (gcc 4.12) 和 Windows (msvc-9.0) 上的相同代码运行良好。
我们可以看到:
- new[] 在堆上分配了内存。
- 内存可访问(我们可以逐字节读取)
- 内存完全包含应有的内容,没有损坏。
那么总线错误的原因可能是什么?我应该去哪里看?
统一更新:
如果我最后 memcpy(...) location 到 original_var,它的工作原理。但是*((const int*)location) 的问题是什么?
【问题讨论】:
-
除了我的答案,正确的地方是在调试器中运行程序,看看哪一行代码使程序崩溃,以及导致总线错误的指针包含什么。然后,您可以再次运行并单步执行以查看设置的位置。
-
@Davislor,不幸的是,这种情况并非一直都在发生。它可能会在 Bus Error 之前进行多次迭代,并且仅在 Solaris 上显示,因此很难调试。
-
另一种调试技术是添加运行时检查。定义一个内联函数,如:
template <type T> inline bool is_aligned( const T* p ) { return (uintptr_t)(void*)(p) % alignof(T) == 0; }。 (如果您没有 C++11,只需跳过模板并使用常量 4 而不是alignof(T)。)然后,每当您进行指针数学运算和转换时,您可以assert将指针is_aligned.如果没有,您将立即使程序崩溃,并诊断出错误发生的位置。 -
哎呀,写了
type我的意思是class或typename。