用memset初始化结构体

Initializing struct with memset

本文关键字:结构体 初始化 memset      更新时间:2023-10-16

我见过这样的代码:

struct TestStruct
{
    int a;
    std::string b;
};

虽然包含std:string,但被初始化为:

TestStruct t;
memset(&t, 0, sizeof(TestStruct));

以我的一些知识和我读过的其他帖子,上面的初始化应该导致程序崩溃(由于struct TestStruct包含std::string),但应用程序似乎没有崩溃,知道为什么吗?谢谢。

这样调用UB,崩溃只是UB的许多表现形式之一。它可能会在稍后的某个(可能不相关的)点崩溃,或者根本不工作。

在你的情况下可能发生的是,std::string在内部只是一个指针,指向一些真正的字符串分配,这是nullptr无论如何已经。但这只是一个猜测,取决于你的实现,可能是月相,并不是可靠的。

崩溃可能是因为您更改了对象的内部状态。像这样初始化:

TestStruct t = { };

更容易在你的手指,也工作在C

在我的64位ubuntu上调用字符串析构函数时会崩溃:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b78bca in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
(gdb) bt
#0  0x00007ffff7b78bca in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x00007ffff7b78c13 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#2  0x0000000000400808 in TestStruct::~TestStruct() ()
#3  0x0000000000400770 in main ()

初始化它本身可能不会导致崩溃,但使用这样的对象是危险的

memset将把std::string对象中的所有数据设置为零,这几乎肯定会给您未定义的行为,当然,可以包括崩溃。我使用的stl (StlPort)有一个奇特的字符串类,它在堆栈上分配短字符串,在堆上分配长字符串。这可能不会在零memset上立即崩溃,但是,真的,没有必要猜测,因为这种行为肯定是不可移植的。

你最好为struct写一个默认构造函数:
TestStruct() : a(0){}

显式将int的内存归零,并依赖于字符串的默认构造函数。

(请记住,类和结构体除了默认访问之外是等效的。)