段错误之memset对类对象的误用

1.问题描述

实际项目中,定义一个如下的基类和子类,均包含有虚函数。

//基类
class OriginalTask {
public:
    OriginalTask() {};
    virtual ~OriginalTask() {};
    virtual bool readFromFileInit(TiXmlElement* const task_element) = 0;
    virtual string createResultFile(TiXmlElement* const task_element, Task* task){}
};

//子类
class DICCUOriginalTask : public OriginalTask {
public:
    bool readFromFileInit(TiXmlElement* const task_element){};
    string createResultFile(TiXmlElement* const task_element, Task* task){};
    DICCUOriginalTask(){};
    ~DICCUOriginalTask(){};

public:
    uint8 algorithm;                        
    uint8 encodeType;       
    uint32 cipher_num;      
    uint32 cipher_len;     
};

使用new定义一个DICCUOriginalTask的对象指针之后,使用memset将对象实体置为0之后,在使用delete析构该对象,就会出现莫名其妙的段错误。

DICCUOriginalTask* dicOriTask=new DICCUOriginalTask;
memset(dicOriTask,0,sizeof(DICCUOriginalTask));
//对dicOriTask的各种处理均未出错
delete dicOriTask;//Segmentation fault (core dumped)

2.问题分析

上面的错误,让我百思不得其解。段错误是指访问的内存超出了系统给这个程序所设定的内存空间,考虑到导致段错误的常见两种情况是: (1)访问系统保护的内存地址,如向地址0写入数据。 (2)内存越界,如数组越界。

当然还有其他的情况,如访问了不存在的内存地址。总而言之,段错误的出现是因为对内存空间的不正确操作。

基于对段错误的理解,本以为是对 dicOriTask处理过程中有不正确的操作,但是几经周折排查后并未发现错误,莫名其妙,原来问题很简单。是memset对类对象的误用。

memset一般用于C语言中对结构体的对象进行置空操作,我却沿用到了C++的类对象。如果类包含有虚函数,那么类对象就会包含有虚函数表指针。如果此时对类对象使用memset置空,那么虚函数表指针也会被置空,当使用delete释放类对象的时候,就会根据虚函数表指针指向的空间去释放虚函数表,那么此时就发生了对内存空间的不正确操作,出现了段错误。

这就是使用memset对类对象的误用。即delete一个被 memset为空的带有虚函数的类对象指针时,就会出现段错误。

3.解决办法

不用使用memset对类对象进行操作,使用类的构造函数对对象进行初始化。

心得:对一个问题感到莫名其妙,那是因为我们知道的太少了。


参考文献

[1]http://blog.163.com/longsu2010@yeah/blog/static/17361234820122761525799/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏视觉求索无尽也

【Python】Python知识点总结

字典{key:value,key:value},dict(key=value,key=value):

50210
来自专栏java一日一条

Java虚拟机体系结构,你知道吗?

众所周知,Java支持平台无关性、安全性和网络移动性。而Java平台由Java虚拟机和Java核心类所构成,它为纯Java程序提供了统一的编程接口,而不管下层操...

10810
来自专栏desperate633

Java动态代理与静态代理静态代理动态代理

我们先看一个简单的例子,当我们需要程序中加入方法执行的日志信息的时候,很显然我们最容易想到的实现方法,就是在方法前后插入日志记录信息。

16420
来自专栏知无涯

XML创建或改变某个新属性

29180
来自专栏决胜机器学习

Shell基本操作与命令

Shell基本操作与命令 (原创内容,转载请注明来源,谢谢) 本文主要是我最近学习shell语言的学习笔记,主要在于通过学习这些内容,达到看得懂shell脚...

36650
来自专栏ShaoYL

iOS 声明属性关键字讲解

371170
来自专栏测试开发架构之路

堆和栈的区别

一、预备知识—程序的内存分配          一个由C/C++编译的程序占用的内存分为以下几个部分     1、栈区(stack)— 由编译器自动分配释放,存...

29380
来自专栏java一日一条

Java虚拟机体系结构,你知道吗?

众所周知,Java支持平台无关性、安全性和网络移动性。而Java平台由Java虚拟机和Java核心类所构成,它为纯Java程序提供了统一的编程接口,而不管下层操...

8820
来自专栏Vamei实验室

Python标准库08 多线程与同步 (threading包)

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢! Python主要通过标准库中的thread...

27650
来自专栏程序员的SOD蜜

实例探究字符编码:unicode,utf-8,default,gb2312 的区别

 最近做邮件收发,不同的邮件系统间可能会出现编码问题,迫使我重新回来研究一下字符的编码问题,unicode,utf-8,gb2312这些编码格式都是我们熟知的,...

258100

扫码关注云+社区

领取腾讯云代金券