Addressof operator returns invalid address in embedded environment
在一个交叉编译的嵌入式Linux环境中调试segfault错误时,我将问题隔离为memset调用。
进一步的调查表明,发生了一些奇怪的事情。我尝试使用以下代码在目标上运行测试应用程序:
1 2 3 4 5 6 7 | string st; st ="teststring"; std::cout <<"address:" << &st << std::endl; std::cout <<"sizeof:" << sizeof(st) << std::endl; std::cout <<"value (before):" << st << std::endl; memset(&st,0,sizeof(st)); std::cout <<"value (after):" << st << std::endl; |
应用程序在memset行上退出,并出现segfault。输出是:
1 2 3 4 5 | address: 0xbed7fb4c sizeof: 4 value (before): teststring Segmentation fault (core dumped) Application finished with exit code 139. |
在桌面环境中编译和运行的相同代码生成以下输出:
1 2 3 4 | address: 0x7ffdc172f7a0 sizeof: 32 value (before): teststring value (after): |
为什么相同的代码在桌面和嵌入式系统上的行为不同?
这两种都是不使用qt组件的qt应用程序。编译器是桌面的gcc和嵌入式系统的buildRootgcc。
memset本身在这里不是问题(由不同的sizeof结果指示)。以下代码还会在嵌入式系统上生成一个segfault:
1 2 3 4 5 6 | string st; st ="teststring"; char* p = (char*)&st; for (size_t i = 0; i != sizeof(st); ++i) { p[i] = 0; } |
如果要清除
第二个示例也是非法的,因为您违反了严格的别名规则。
你试图执行非法操作。
要在对象上使用
如果你真的,真的想以字符数组的形式访问字符串,你可以说
1 2 3 4 | char* p = &st[0]; for (size_t i = 0; i != st.size(); ++i) { p[i] = 0; } |
为了增加给出的答案,如果你想确保你不创建这样的程序(比如调用EDOCX1[2]),使用类型特征和std::是非常容易复制的
1 2 3 4 5 6 7 8 | #include <type_traits> #include <string> int main() { static_assert(std::is_trivially_copyable<std::string>(), "Sorry, you're memset is not going to work"); } |
现在,由于给定的
与此相比:
1 2 3 4 5 6 7 8 9 10 11 12 | #include <type_traits> struct foo { char x[10]; }; int main() { static_assert(std::is_trivially_copyable<foo>(), "Sorry, you're memset is not going to work"); } |
编译时没有错误,因为