删除指向子类的基类指针,报重复释放错误!!!

jovial__ 2012-03-03 02:10:20
我的目的是做个词性标注的东西;可以支持英语和中文;
想法是:由基类派生中文子类和英文子类;在对外调用接口,就可以通过制定语言id来 给基类指针生成哪种语言的子类了;
执行都很成功;但是在最后释放指针的时候,出现这个错误;
*** glibc detected *** double free or corruption (!prev): 0x00000000008acb00 ***

我的头文件定义是这样的:

外部调用接口postag.h

class PostagModel {
public:
/**
* @brief 构造函数
**/
PostagModel() {
m_pImpt = NULL;
m_bOpen = false;
};

/**
* @brief 析构函数
*
**/
~PostagModel() {
printf("~postagmodel\n");
fflush(stdout);
}

/**
* @brief 根据模型文件的目录和语言id,创建模型
* @param[in] model_file_dir : const char* 模型文件目录
* @param[in] lang_id : const unsigned 语言ID: 1=english 0=chinese
* @return true=成功 false=失败
**/
bool create(const char *model_file_dir, const unsigned lang_id);

/**
* @brief 标注函数
* @param[in] words : const vector<string> & 句子向量,词条组成基本单位
* @param[out] tags : vector<string> 返回的标注tags序列
* @param[in] hmm_order : const unsigned 解码阶数
* @return true=成功 false=失败
**/
bool postag(const vector<string> &words, vector<string> &tags, const unsigned hmm_order);

/**
* @brief 释放资源
*
**/
void destroy();
private:
PostagModelImplement *m_pImpt; //模型实现接口
bool m_bOpen; //是否已经打开模型
};


内部头文件postag_model.h

#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <vector>
#include <cstdio>
using namespace std;

#include "HmmModel.h"

//基类
class PostagModelImplement {
public:
/**
* @brief 构造函数
*
**/
PostagModelImplement() {};

virtual ~PostagModelImplement() {};

/**
* @brief 初始化postag_model模型,postag内部初始化调用接口
**/
bool init_postag_model(const char *model_file_dir);

/**
* @brief 词性标注
* @param[in] words : const vector<string>& 词向量(明文)
* @param[out] tags : vector<string>& 词性序列
* @param[in] hmm_order : 指定几阶解码1/2
**/
bool postag(const vector<string> &words, vector<string> &tags, const unsigned hmm_order);

/**
* @brief 归一化oov,并利用归一化的oov获取oov的映射id
**/
virtual int normalizeOov_to_oovId(const char *oov) = 0;

/**
* @brief 判断是否为数字
**/
virtual bool is_CD_string(const char * str) = 0;

/**
* @brief 销毁postag_model
**/
void destroy();
protected:
map<string, int> word2Id; //word到id映射的存储结构
map<string, int> low_oov2Id;
map<string, int> up_oov2Id;
map<int, string> tagId2tag; //tagId到tag的映射,采取N维字符串形式存储,方便直接索引
private:
HmmModel m_hmm_model; //HMM解码接口

/**
* @brief 加载word2id、lowoov2id、upoov2id、tagid2tag文件的行数
**/
bool PostagModelImplement::load_linenum(const char* linenum_file);

/**
* @brief 加载word到wordId的映射关系
**/
bool load_word2Id(const char* word2Id_file);

/**
* @brief 加载oov到oovId的映射关系
**/
bool load_oov2Id(const char* oov2Id_file);

/**
* @brief 加载tagId到tag的映射关系
**/
bool load_tagId2tag(const char* tagId2tag_file);

/**
* @brief 将词序列映射为词id序列
**/
bool trans_word_to_wordId(vector<string>, int*);
};


/**
* 英文语言扩展类
**/
class EnglishPostagModelImpt : public PostagModelImplement {
public:
/**
* @brief EnglishPostagModel构造函数
**/
EnglishPostagModelImpt() {};

/**
* @brief 析构函数
**/
~EnglishPostagModelImpt() {};

/**
* @brief 英文,获取oov的id
**/
virtual int normalizeOov_to_oovId(const char *_oov);

/**
* @brief 是否是数字
**/
virtual bool is_CD_string(const char * str) ;
};

/**
* 中文语言扩展类
**/
class ChinesePostagModelImpt : public PostagModelImplement {
private:
map<string, int> *ch_oov2Id;
public:
ChinesePostagModelImpt() {};

~ChinesePostagModelImpt() {};

/**
* @brief 中文,获取oov的id
**/
virtual int normalizeOov_to_oovId(const char *_oov);

/**
* @brief 是否为数字串
**/
virtual bool is_CD_string(const char *str);
};



其中的部分实现是:

void PostagModel::destroy() {
m_pImpt->destroy();
delete m_pImpt;//报错报在这
m_pImpt = NULL;
m_bOpen = false;
}



bool PostagModel::create(const char *model_file_dir, const unsigned lang_id) {
if(model_file_dir == NULL || lang_id > 1) {
return false;
}
if(m_pImpt != NULL) {
delete m_pImpt;
m_pImpt = NULL;
}

if(lang_id == 0) { //中文
m_pImpt = new ChinesePostagModelImpt();
if(m_pImpt == NULL) {
goto failed;
}

} else if(lang_id == 1) { //英文
m_pImpt = new EnglishPostagModelImpt();
if(m_pImpt == NULL) {
goto failed;
}
} else { //其他
goto failed;
}

if (m_pImpt == NULL)
{
goto failed;
}

if(m_pImpt->init_postag_model(model_file_dir) == false) {
goto failed;
}

m_bOpen = true;

failed:
if (!m_bOpen && m_pImpt)
{
delete m_pImpt;
m_pImpt = NULL;
}

return m_bOpen;
}


我的代码里面并没有对m_pImpt进行重复删除,会不会其他问题导致这个报警错误呢?

或是我的类与子类使用错误导致的?
但是程序运行的结果是正确的;就是在释放资源destrory()执行的时候出错了。
...全文
165 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
quwei197874 2012-03-03
  • 打赏
  • 举报
回复
用虚的析构函数
jovial__ 2012-03-03
  • 打赏
  • 举报
回复
在执行delete m_pImpt的时候,子类和基类的析构函数能执行(有打印信息输出),但就是delete操作跳不出来;
jovial__ 2012-03-03
  • 打赏
  • 举报
回复
另外 ,我在create()里面的 m_pImpt = new EnglishPostagModelImpt(); 这句话执行之后,直接运行

delete m_pImpt也会报错;

怀疑是不是其他地方写错了;而不是资源释放有问题?
jovial__ 2012-03-03
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 dobzhansky 的回复:]

看到
m_pImpt->destroy();
delete m_pImpt;
m_pImpt = NULL;

这样的代码, 会直觉的以为 destroy() 内部会调用 delete this;

究竟是靠析构函数来管理资源, 还是加上一个类似 com 那样的 release(destroy) 呢,
都可以, 一致就好.

代码风格好
[/Quote]
这个destroy()里面是进行 执行解码的资源释放HMM_model.destroy(); 就这一句话;
Dobzhansky 2012-03-03
  • 打赏
  • 举报
回复
看到
m_pImpt->destroy();
delete m_pImpt;
m_pImpt = NULL;

这样的代码, 会直觉的以为 destroy() 内部会调用 delete this;

究竟是靠析构函数来管理资源, 还是加上一个类似 com 那样的 release(destroy) 呢,
都可以, 一致就好.

代码风格好
pengzhixi 2012-03-03
  • 打赏
  • 举报
回复
m_pImpt->destroy();
你先说说这个里面你做了什么吧

64,647

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧