地址操作符在嵌入式环境中返回无效地址
Addressof operator returns invalid address in embedded environment
在交叉编译的嵌入式linux环境中调试段错误时,我将问题隔离为memset调用。
进一步的调查表明,有些奇怪的事情正在发生。我尝试用以下代码在目标上运行一个测试应用程序:
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行上出现段错误。输出为:
address: 0xbed7fb4c
sizeof: 4
value (before): teststring
Segmentation fault (core dumped)
Application finished with exit code 139.
在桌面环境中编译和运行的相同代码产生以下输出:
address: 0x7ffdc172f7a0
sizeof: 32
value (before): teststring
value (after):
为什么相同的代码在桌面和嵌入式系统上的表现不同?
都是不使用Qt组件的Qt应用程序。编译器是用于桌面的GCC和用于嵌入式系统的builroot GCC。
Memset本身不是这里的问题(正如不同的sizeof结果所表明的那样)。下面的代码也会在嵌入式系统上产生段错误:
string st;
st = "teststring";
char* p = (char*)&st;
for (size_t i = 0; i != sizeof(st); ++i) {
p[i] = 0;
}
std::memset
要求您传递给它的对象是可复制的。std::string
是不可复制的,所以它是未定义的行为调用memset
。
如果您想清除string
的内容,那么您应该在实例上调用clear
。
你的第二个例子也是非法的,因为你违反了严格的混叠规则。std::string
不是c字串。不能将字符串对象的地址作为底层c-string中的第一个字符。众所周知,字符串的大小首先存储在类中,您将用垃圾覆盖它。
您正在尝试执行非法操作。
要在一个对象上使用std::memset
,它必须是一个聚合。std::string
不是其中之一。如果你想用0填充它,使用std::fill
。如果你只想让它为空,使用clear()
。
如果你真的,真的想访问字符串作为字符数组,你可以说
char* p = &st[0];
for (size_t i = 0; i != st.size(); ++i) {
p[i] = 0;
}
&st[0]
给出第一个字符的地址,字符串保证数据的连续内存布局。
为了补充给出的答案,如果您想确保不创建这样的程序(例如调用memset
),请使用类型特征和std::is_trivially_copyyable
#include <type_traits>
#include <string>
int main()
{
static_assert(std::is_trivially_copyable<std::string>(),
"Sorry, you're memset is not going to work");
}
现在程序将无法编译,更不用说运行了,因为给定的类型std::is_trivially_copyable
无法通过static_assert。
与此比较:
#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");
}
编译时没有错误,因为foo
是可复制的。type_traits在这里是你的朋友。
- 从 C++ 中的函数返回数组地址问题
- inet_ntop返回不存在的地址
- 为什么下面的代码段返回指针指向的值而不是指针的地址?
- 为什么使用存储在虚拟方法表中的地址调用虚拟函数的函数会返回垃圾?
- 为什么按值返回的对象与方法中的对象具有相同的地址?
- 返回数组中值的指针地址
- 创建一个函数来转换数组元素的类型并返回数组的地址
- 返回地址上的WriteProcessMemory
- 指针地址的内存偶尔更改了函数前和后返回
- libmysql:警告:返回局部变量"行"的地址(C++/C)
- 在字符串函数的指针中返回地址
- 在C++中为零大小的分配返回唯一地址背后的基本原理是什么?
- 重载新返回错误的地址
- 为什么 C++ 中的字符数组返回其项目而不是地址?
- 为什么 c_str() 在返回常量指针值时不输出地址
- 英特尔 Pin:如何获取系统调用的返回地址
- 按价值和地址返回
- ReadProcessMemory()为静态地址返回0
- 访问存储在指针变量所指向的地址中的值(这是一个地址)返回垃圾值
- 将地址返回给局部变量与返回指向局部变量的指针