C++ 使用memset初始化struct
我见过这样的数据结构的代码:C++ 使用memset初始化struct,c++,C++,我见过这样的数据结构的代码: struct TestStruct { int a; std::string b; }; 虽然其中包含std:string,但初始化为: TestStruct t; memset(&t, 0, sizeof(TestStruct)); 根据我的一些知识和我读过的其他帖子,上面的初始化应该 由于struct TestStruct containst std::string导致程序崩溃,但应用程序似乎没有崩溃,你知道为什么吗? 谢谢。你用它来
struct TestStruct
{
int a;
std::string b;
};
虽然其中包含std:string,但初始化为:
TestStruct t;
memset(&t, 0, sizeof(TestStruct));
根据我的一些知识和我读过的其他帖子,上面的初始化应该
由于struct TestStruct containst std::string导致程序崩溃,但应用程序似乎没有崩溃,你知道为什么吗?
谢谢。你用它来调用UB,崩溃只是UB的众多化身之一。它可能会在稍后的某个可能不相关的点崩溃,或者根本不起作用
在您的例子中可能发生的情况是,std::string在内部只是一个指向某个实际字符串分配的指针,无论如何,它已经是null ptr了。但这只是一个猜测,取决于您的实现,可能是月球阶段,不可依赖。您用它调用UB,崩溃只是UB的众多化身之一。它可能会在稍后的某个可能不相关的点崩溃,或者根本不起作用
在您的例子中可能发生的情况是,std::string在内部只是一个指向某个实际字符串分配的指针,无论如何,它已经是null ptr了。但这只是一个猜测,取决于您的实现,可能是月球阶段,不可依赖。初始化本身可能不会导致崩溃,但使用此类对象是危险的初始化本身可能不会导致崩溃,但是使用这样的对象是危险的调用字符串析构函数时,它会在我的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 ()
调用字符串析构函数时,它在我的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 ()
由于更改对象的内部状态,可能会发生崩溃。改为如下初始化:
TestStruct t = { };
手指更容易操作,在C语言中也能工作。由于更改对象的内部状态,可能会发生崩溃。改为如下初始化:
TestStruct t = { };
更简单,在C语言中也可以使用。memset会将std::string对象中的所有数据设置为零,这几乎肯定会给您带来未定义的行为,当然,其中可能包括不崩溃。我使用StlPort的stl有一个奇特的string类,它在堆栈上分配短字符串,在堆上分配长字符串。这可能不会在零内存集上立即崩溃,但实际上,没有必要进行猜测,因为这种行为肯定是不可移植的
最好为结构编写一个默认构造函数:
它显式地将int的内存归零,并依赖于字符串的默认构造函数
请记住,除了默认访问之外,类和结构是等效的。memset会将std::string对象中的所有数据设置为零,这几乎肯定会给您带来未定义的行为,当然,其中可能包括不崩溃。我使用StlPort的stl有一个奇特的string类,它在堆栈上分配短字符串,在堆上分配长字符串。这可能不会在零内存集上立即崩溃,但实际上,没有必要进行猜测,因为这种行为肯定是不可移植的
最好为结构编写一个默认构造函数:
它显式地将int的内存归零,并依赖于字符串的默认构造函数
请记住,除了默认访问之外,类和结构是等效的。它不必导致崩溃。这是未定义的行为。您仍然需要修复它。您只是非常幸运。@MarkGarcia我会说不幸运。您可以使用结构构造函数代替。它不一定会导致撞车。这是未定义的行为。您仍然需要修复它。您只是非常幸运。@MarkGarcia我会说不幸运。您可以使用结构构造函数代替。因为std::字符串b;在结构内部?如果我只有基本类型,那就可以了,对吗?memset已经调用UB了,这很危险。@pseuronym_127如果我只有基本类型,那就可以了,对吗?使用的术语是POD纯旧数据,是的,在这种情况下它是可以的;在结构内部?如果我只有基本类型,那就可以了,对吗?memset已经调用UB了,这很危险。@pseuronym_127如果我只有基本类型,那就可以了,对吗?使用的术语是POD纯旧数据,是的,在这种情况下可以。这是显式地将所有成员初始化为0/null默认值,还是需要一个结构构造函数来实现这一点?该链接只处理显式值规范,上面的语法有空括号,这意味着类似于默认初始化的东西……尽管链接明确表示必须没有构造函数才能使用结构S={a,b,c};语法。@Deniseskimore…因此我发布了正确的链接…这是显式地将所有成员初始化为0/null默认值,还是需要一个结构构造函数来实现这一点?该链接只处理显式值规范,上面的语法有空括号,I
隐含一些类似于默认初始化的东西……尽管链接明确表示不能有构造函数来使用结构S={a,b,c};语法。@Deniseskimore…因此我发布了正确的链接。。。