简体   繁体   English

做memset时出现段故障

[英]Seg Fault while doing memset

While running the below program, I am getting segfault. 运行以下程序时,我遇到了段错误。 But if I comment memset, I am not getting seg fault. 但是,如果我评论memset,则不会出现段错误。 Not able to figure out the reason. 无法找出原因。 What we can do instead of memset, if I need to clear the structure contents(such as value)? 如果需要清除结构内容(例如值),我们可以代替memset做什么?

#include <iostream>
#include <cstring>
#include <map>
using namespace std;

struct test
{
    int value;
    map<int, int> m;
};

void print(test *ptr)
{
    cout << "map size() : " << ptr->m.size();
    for(auto itr = ptr->m.begin(); itr != ptr->m.end(); ++itr)
    {   
    }   
}

int main()
{
    test obj;
    memset(&obj, 0, sizeof(obj));
    print(&obj);
}

std::map is not a POD structure, so it has internals (such as pointers and etc) which will be initialized in it's contructor. std::map不是POD结构,因此它具有内部结构(例如指针等),这些内部结构将在其构造函数中初始化。

When you call memset , you zeroed the entire structure, making any access to it undefined behavior. 调用memset ,您将整个结构归零,从而对其进行的任何访问均未定义。

And then you call function size() , which crash your code, because it tries to read any internal which is at zero address now. 然后调用函数size() ,这会使您的代码崩溃,因为它尝试读取现在位于零地址的任何内部。

Live Demo on cpp.sh cpp.sh上的实时演示

Instead of memset you should use specified method of std::map -> clear() , when you want to clear it. 如果要清除它,则应使用std::map > clear()指定方法来代替memset

Calling memset on a type that is not trivially copyable is undefined behaviour ( https://en.cppreference.com/w/cpp/string/byte/memset ). 在不可复制的类型上调用memset是未定义的行为( https://en.cppreference.com/w/cpp/string/byte/memset )。 std::map is not trivially copyable, therefore your struct test also is not. std::map不可复制,因此您的结构test也不能复制。

If you want to set value to 0, you can just call obj.value = 0 , and if you want to clear m , you can call obj.m.clear() . 如果要将value设置为0,则只能调用obj.value = 0 ,如果要清除m ,则可以调用obj.m.clear()

std::memset is only intended for objects that are trivially copyable. std::memset仅适用于平凡可复制的对象。 For something like std::map (which is a component of test ), that's undefined behavior. 对于诸如std::map类的东西(这是test的组成部分),这是未定义的行为。

While a default-initialized int is going to be an inderminate value, std::map has a default constructor and as will start with its own, correct bookkeeping. 虽然默认初始化的 int将是一个Inderminate值,但std::map具有默认的构造函数,并且将以其自己的正确记账开始。 But that gets quashed by std::memset . 但这被std::memset取消了。

You pretty much don't need std::memset in C++. 在C ++中,您几乎不需要std::memset

One quick and dirty option is to value-initialize test . 一种快速而肮脏的选择是对test进行值初始化 This zero-initializes values of non-class types such as int : 零初始化非类类型的值,例如int

test obj{}

To reset it you'd do 要重置它,你会做

obj = test{}

An even better option is to give test a default constructor which sets m to zero. 更好的选择是给test一个默认的构造函数,该构造函数将m设置为零。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM