半天时间找到原因却仍未解决的Bug


半天时间找到原因却仍未解决的Bug

在一个巨大的数据文件作为输入时, 出现了一个assert断言错误.
花了半天时间跟踪代码, 费尽心思找到了错误的来源,
可是一时间也没有解决的办法, 只能打个临时补丁.

类里面有个成员变量
    std::ofstream m_ofs;
   
在某个方法里面的断言警告:
    assert(!m_ofs);
       
流操作之后都有一个状态判断:
    if (!m_ofs)
    {
        log...
        m_ofs.close();
        return;
    }
为什么会有错误的流状态?

但是open()操作后判断失败没有关闭流.
    m_ofs.open(sPath);
    if (!m_of)
    {
        log...
        return;
    }

表面上看是ofstream::open()打开文件出错了.
open()出错时只写了一条日志, 没做处理.
这个ofstream对象m_ofs不是临时对象, 而是类内嵌对象.
下一次使用时, 发现m_ofs处于已打开状态, 而流状态是错误的,

以为open()失败后文件会处于关闭状态, 看来是错误的.
open()失败后加了一个close()试了试,还是有流错误。

open()为什么会出错? strerror(errno)显示"No error".
以为是errno没有正确指示错误, 再跟踪进入open()代码, 发现open()其实是成功了.
m_ofs是在open()之前就已经fail了(查看内部状态State=2, 即failbit位).

一定是上次close()后failbit并没有清除.
close()成功情况下, 会执行clear(), 但有可能close()失败.

添加clear()在所有close()之前.
可是failbit象是凭空出现, clear()并没有起作用.

回忆历史代码, 原来只有临时变量的流, 用完就自动关闭了.
而为了对付频繁的同一文件打开, 流对象改为了内部成员变量.
而流的宿主类间接地是另一个类的成员变量, 该类是某stl容器类的元素.

问题就在这里了, stl容器类会使用其元素类的拷贝构造函数来复制元素.
一定是ofstream通过这样的复制后产生了错误的状态.
而宿主类及其上层也没有提供拷贝构造函数, 只有默认的浅拷贝.
如果没有这个流, 这些类都是一些简单数据类, 完全可以使用默认的字节拷贝.

浅拷贝不行, 深拷贝不能, 结果是找到原因, 却不知如何修改.
只能暂时恢复为临时流变量.
不过最终还应该支持大量的文件打开关闭操作, 不知怎么办.

心得:
* 没有必要就不要保存一个流变量,使用临时变量可保证文件打开与关闭是成对的。
* stl容器最好只存放简单数据,可避免自定义拷贝构造函数。
如果元素类较复杂,应考虑使用指针,因为有可能今后的修改后使元素类更复杂。
* ofstream::close()可能不会清除错误状态,并可能置failbit,如未打开就关闭。
上面的clear()应加在close()之后。

问题:
* 如何添加单元测试,使得一个类保证为简单数据类,或保证stl容器可安全使用?
* 不能实现深拷贝时,有没有办法解决浅拷贝问题?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值