Addressof运算符在嵌入式环境中返回无效地址

在交叉编译的嵌入式Linux环境中调试segfault错误时,我将问题隔离为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行中以segfault退出。 输出是:

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和嵌入式系统的buildroot gcc。

Memset本身在这里不是问题(如不同大小的结果所示)。 以下代码也会在嵌入式系统上产生段错误:

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字符串中的第一个字符。 对于所有你知道的字符串的大小首先存储在类中,并用垃圾覆盖。


您正在尝试执行非法操作。

要在对象上使用std::memset ,它必须是一个聚合。 std::string不是一个。 如果你想用零填充,使用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是你的朋友。

链接地址: http://www.djcxy.com/p/15249.html

上一篇: Addressof operator returns invalid address in embedded environment

下一篇: Makefile library prerequisite