C++初始化列表引起的bug

来源:互联网 发布:免费淘宝全套模板下载 编辑:程序博客网 时间:2024/06/04 19:07

   最近想把谷歌quic协议中的simulator单独摘取出来,供自己使用。但是程序的调试的时候,遇见一个诡异的bug。感觉可以意会,不可言传。

   就是说,在类中进行列表初始化的时候,类(A)中的私有成员变量(B)在列表中初始化,而这个私有类(B)在构造的时候,回调了类(A)的未初始化私有变量(C),程序运行的时候就会死掉。就是列表初始化的时候,还未对私有成员类(C)进行初始化,于是引起bug。也可以说,列表初始化是与成员中的顺序是有关的。

   bug复现如下:

main.cpp

#include<iostream>#include"simulator.h"#include "actor.h"int main(){    simulator::Simulator *simulator;    simulator=new simulator::Simulator();    printf("in main function\n");}

simulator.h

#ifndef __SIMULATOR_H__#define __SIMULATOR_H__#include<unordered_map>#include<unordered_set>#include"actor.h"#include<utility>#include<memory>namespace simulator{class Actor;class Alarm;class Simulator{public:    Simulator();    ~Simulator();void AddActor(Actor *actor);private:    int counter_;    std::unique_ptr<Alarm>alarm_;    std::unordered_map<Actor*,int>schedule_count_;    std::unordered_set<std::string>actor_names_;};}#endif // __SIMULATOR_H__

simulator.cc

#include"simulator.h"#include<stdio.h>#include"alarm.h"namespace simulator{Simulator::Simulator():counter_(0),alarm_(new Alarm(this)){}Simulator::~Simulator(){}void Simulator::AddActor(Actor *actor){    printf("add Actor %d\n",counter_);    schedule_count_.insert(std::make_pair(actor,counter_));    actor_names_.insert(actor->name());}}
actor.h

#ifndef __ACTOR_H_#define __ACTOR_H_#include "simulator.h"namespace simulator{class Simulator;class Actor{public:    Actor(Simulator *simulator,std::string name);    virtual ~Actor();    std::string name(){return name_;}private:    Simulator *simulator_;    std::string name_;};}#endif // __ACTOR_H_
actor.cc
#include"actor.h"#include "simulator.h"namespace simulator{Actor::Actor(Simulator *simulator,          std::string name):simulator_(simulator),          name_(name){simulator_->AddActor(this);}Actor::~Actor(){}}

alarm.h

#ifndef __ALARM_H__#define __ALARM_H__#include "simulator.h"#include "actor.h"namespace simulator{class Alarm:public Actor{public:    Alarm(Simulator *simulator):Actor(simulator,std::string("alarm")){}    ~Alarm()override{}};}#endif // __ALARM_H__

增加一个编译使用的CMakeFiles.txt

PROJECT(project)cmake_minimum_required(VERSION 2.6)SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Wall  -O2")SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -O2")include_directories(.)add_definitions(-std=c++11)set(SOURCE_FILESmain.cppactor.ccsimulator.cc)set(EXECUTABLE_NAME "demo")add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES})


程序是在Simulator::AddActor中崩溃的,这个问题是在初始化函数Simulator::Simulator():counter_(0),alarm_(new Alarm(this)){}中引入的。就是simulator中的变量alarm回调了simultor中的AddActor函数,而这个函数中的哈希表schedule_count_在这个时候尚未初始化。

解决的办法,就是将这个部分放入构造函数中去。修改为:Simulator::Simulator():counter_(0){alarm_.reset(new Alarm(this));}