做memset时出现段故障

时间:2018-08-06 10:55:31

标签: c++ c++11

在运行以下程序时,我遇到了段错误。但是,如果我评论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);
}

3 个答案:

答案 0 :(得分:7)

std::map不是POD结构,因此它具有内部结构(例如指针等),它将在其构造函数中初始化。

调用memset时,您将整个结构置零,使对其的任何访问都不确定。

然后调用函数size(),该函数使您的代码崩溃,因为它尝试读取现在位于零地址的任何内部。

Live Demo on cpp.sh

要清除它,请使用memset-> std::map的指定方法代替clear()

答案 1 :(得分:6)

在不可复制的类型上调用memset是未定义的行为(https://en.cppreference.com/w/cpp/string/byte/memset)。 std::map不可复制,因此您的结构test也不可复制。

如果要将value设置为0,则可以仅调用obj.value = 0,而如果要清除m,则可以调用obj.m.clear()

答案 2 :(得分:2)

std::memset仅适用于平凡可复制的对象。对于std::map(是test的组成部分)之类的东西,这是未定义的行为。

尽管default-initialized int将是一个整数值,但是std::map具有默认构造函数,并且将以其自己的正确簿记开始。但这被std::memset取消了。

在C ++中,您几乎不需要std::memset

一个快捷而肮脏的选择是value-initialize test。这将对非类类型的值(例如int)进行零初始化:

test obj{}

要重置它,

obj = test{}

一个更好的选择是给test一个默认的构造函数,该构造函数将m设置为零。