注:这篇日志是好多年前,我还在从兴公司时写的。现在都从从兴公司离职很久了,从兴也没落了,可惜。看了一下,虽然出现了部分代码,但不至于泄漏什么机密,查bug过程的原理也有可以让新手借鉴的地方,就原文照搬上来了。

  dbtool是营帐研发部常用的一个类sqlplus数据库查询工具,它提供了较sqlplus更友好的输出界面,十分适合在命令行下操作,故在部门内部使用相当广泛。

不过它一直有一个bug,使用过程中偶尔会出现执行某条sql后core down的情况。但是由于这种情况较少见,而且bug出现随机性太大,所以一直也没人去管它。

今天早上加班过程中,居然又让我碰上这个bug了。不过这次bug很有规律,每次连接上数据库后立即执行“select userenv('language') from dual;”程序立即core down。

由于是周日,比较有空,而且天赐良机,居然能重现bug,于是决定花点时间解决这个bug。

首先使用dbx看一下程序在哪core

Segmentation fault(coredump)
bbkf:/home/report/c++/report/dbtool$dbx dbtool
Type 'help' for help.
[using memory image in core]
reading symbolic information ... Segmentation fault in malloc_y at 0x90000000005bb10 ($t1)
0x90000000005bb10 (malloc_y+0x5a4) stw r0,0x0(r5)
(dbx) where
malloc_y(0xa1, 0x0, 0x0, 0x7f7f7f7f, 0x2, 0x2d2d0049, 0x2d, 0x100233704) at 0x90000000005bb10
malloc_common_79_63(??) at 0x900000000058948
_Fancy_malloc__FUl(??) at 0x900000000451ae4
__nw__FUl(??) at 0x9000000004517c0
_Allocate__3stdHc_UlPc_Pc(??, ??) at 0x9000000004c5834
allocate__Q2_3std9allocatorXTc_FUlPCv(??, ??, ??) at 0x9000000004c57c4
_Copy__Q2_3std12basic_stringXTcTQ2_3std11char_traitsXTc_TQ2_3std9allocatorXTc__FUl(??, ??) at 0x9000000004c564c
_Grow__Q2_3std12basic_stringXTcTQ2_3std11char_traitsXTc_TQ2_3std9allocatorXTc__FUlb(??, ??, ??) at 0x9000000004c4ec8
assign__Q2_3std12basic_stringXTcTQ2_3std11char_traitsXTc_TQ2_3std9allocatorXTc__FPCcUl(??, ??, ??) at 0x9000000004c4bac
assign__Q2_3std12basic_stringXTcTQ2_3std11char_traitsXTc_TQ2_3std9allocatorXTc__FPCc(??, ??) at 0x9000000004c4974
__ct__Q2_3std12basic_stringXTcTQ2_3std11char_traitsXTc_TQ2_3std9allocatorXTc__FPCc(??, ??) at 0x9000000004c4880
GetColNameDisplay(std::basic_string<char,std::char_traits<char>,std::allocator<char> >&,std::basic_string<char,std::char_traits<char>,std::allocator<char> >&)(this = 0x0fffffffffffaba8, colsName = &(...), prompt = &(...)), line in "cmdDeal.cpp"
GetDBData(int)(this = 0x0fffffffffffaba8, bAutoContinue = ), line in "cmdDeal.cpp"
CCmdDeal::Run()(this = 0x0fffffffffffaba8), line in "cmdDeal.cpp"
main(argc = , argv = 0x0ffffffffffff338), line in "dbtool.cpp"
(dbx)

  从上面可以看到,出错位置在string里面,根据经验,这种bug好解决,一般是string操作错误,例如将一个没有\0结尾的字符数组赋值给string

用vi打开cmdDeal.cpp,定位到884行,发现如下代码

  +875  int CCmdDeal::GetColNameDisplay(string &colsName, string &prompt)
+876 {
+877 char chSplit = ' ';
+878 int i, len = 0;
+879 int rows = 0;
+880 int maxNameLen = 0;
+881 int lineSize = 0;
+882 int displayMode = 0;
+883 string s;
+884 string str45 = "-------------------------------------------------------------------"
+885 "-------------------------------------------------------------------";

居然是正常的字符串初始化出错! 这就郁闷了,这行代码怎么看都是正常的,根据经验,这种正常的代码出错,一般是由于前面某个位置出现了越界操作导致的。这种错误相对难查很多。

浏览了一下附近的代码,都没发现什么异常的代码,于是只能加上一些调试代码看能不能找出问题。经过一番尝试后发现,在GetColNameDisplay里面初始化长度较大的字符串就会导致程序core down。并且这个规律在GetDBData(调用GetColNameDisplay的函数)里面也有效。

这就好办了,只要找出在哪段代码执行后会出现这种奇怪的现象,问题代码应该就在那。

  于是在程序里面加了N多个下面的代码片段

 {
string str45 = "-------------------------------------------------------------------"
"-------------------------------------------------------------------";
string str451 = "-------------------------------------------------------------------"
"-------------------------------------------------------------------";
printf("[%s:%d]\n", __FILE__, __LINE__);
}

上面的调试代码特意括在大括号里面的,目的有两个,

  1 括号使得str45变成局部变量,这样不会出现变量冲突

  2 保证str45尽快析构,以免影响错误定位

  加上代码后编译运行,看程序在哪两行代码之间挂掉,接着在那两行代码中间增加更多调试代码,反复运行,很快就定位到了出错函数GetColumnInf。程序在调用这个函数之前调试代码执行不会有问题,在之后就挂了。GetColumnInf这个函数比较短,仔细看了一下,发现下面这段代码可能有问题。

 vector<ColInf>::iterator it = m_vecColInf.begin();
int Index = ;
COciCursor cur( *m_pOracle );
COciColumnDesc coldesc; cur.Parse(strSql.c_str()); do
{
cur.DescribeColumn( Index, coldesc );
if (it->type != && it->type != )
{
it->prec = it->type== ? it->prec : coldesc.m_Prec;
}
it++;
Index++;
} while ( !cur.EndOfDesc() );
cur.Close();

  代码里面对it操作时,没有判断it是否越界,整个函数看起来就这个最可能出现问题了。试着给while循环加了一个判断条件变成“while ( !cur.EndOfDesc() && it != m_vecColInf.end() );”

重新编译运行。

 jmzw@boss15test >select userenv('language') from dual; 

 USERENV('LANGUA
-------------------------
AMERICAN_AMERICA.ZHS16GBK rows selected.

  猜对了,程序能正确输出,不会再core掉! 接下只需要分析这段代码为何会越界,修复即可。不过一看时间已经十一点多,不知不觉浪费了近半个上午,而且这段代码看起来作用只是获取数据库字段精度,不是很重要,所以此次根跟踪到此为止吧。

  此次收获经验:写代码还是谨慎点,加多一些边界判断比较好,不然贪图一时方便可能导致花大把时间在定位bug

dbtool一bug跟踪记的更多相关文章

  1. Bug跟踪方法

     Bug跟踪函数调用方法 StackTraceElement mSte = new Exception().getStackTrace()[1]; Log.e("mmm", mSt ...

  2. Bug跟踪的流程

    本文以翼发云协同项目管理系统为例子来讲解Bug跟踪的流程,它以工作流为中心的集成式Bug跟踪软件,它广泛地应用于研发行业的产品缺陷管理 与跟踪.事务跟踪.问题跟踪.任务跟踪.查询跟踪.需求管理.变更跟 ...

  3. Android分组子级的不同视图布局之BUG奇遇记

    Android分组子级的不同视图布局之BUG奇遇记 最近在使用按日期分类列表,二级条目可能不一样,于是就想到了ExpandableListView. ExpandableListView的布局显示分割 ...

  4. 提高效率!15款最好的 Bug 跟踪应用程序

    当涉及到开发项目时,其中比较重要的事情是它需要某​​种形式的错误和问题跟踪工具来发现和解决问题,否则会浪费大量的时间. 此外,你总是要标签应用来标示那些悬而未决的问题,而这种分期执行的项目进度将帮助您 ...

  5. Visual Studio App Center 中的 Bug 跟踪服务

    我在之前的一篇文章 <使用 Visual Studio App Center 持续监视应用使用情况和问题> 中介绍了 App Center 的基本功能及使用入门,其中 诊断 可以自动手机用 ...

  6. [异常特工]android常见bug跟踪

    前言 对app的线上bug的收集(友盟.云捕等)有时会得到这样的异常堆栈信息:没有一行代码是有关自身程序代码的.这使得对bug的解决无从下手,根据经验,内存不足OOM,Dialog关闭,ListVie ...

  7. 线上应用bug跟踪查找-友盟统计

    线上的应用只要用心点点都能发现些bug,连微信,QQ也不列外.但是bug中最严重的算是闪退了,这导致了用户直接不能使用我们的app. 我们公司是特别注重用户反馈和体验的,我们会定期打电话咨询用户的使用 ...

  8. bug生命周期&bug跟踪处理

    一.BUG BUG:软件的缺陷 1.BUG的定义:----与软件测试的目的对应 软件的BUG,狭义概念是指软件程序的漏洞或缺陷,广义概念除此之外还包括测试工程师或用户所发现和提出的软件可改进的细节.或 ...

  9. 测试人必备:国内外最好用的6款Bug跟踪管理系统

    在移动互联网产品中,Bug会导致软件产品在某种程度上不能满足用户的需要.确保一个项目进展顺利,关键在于妥善处理软件中的BUG,那么,如何高效的管理BUG,解决BUG?在这里,我为大家搜集了几款优秀的B ...

随机推荐

  1. Monkeyrunner测试环境搭建

    Monkey手机APP压力测试,是对手机发送伪随机命令,对手机进行按键,触摸等操作,MonkeyRunner是对其发送重复操作的命令,是Monkey的进阶版,可以设置重复的操作或者是重现步骤等.相比较 ...

  2. 如何在Ubuntu中添加中文输入法

    首先打开终端,输入以下命令 打开终端输入以下命令 弹出设置IBus首选项对话框,单击输入法文本框,再单击添加按钮,选中汉语中的拼音,单击添加,设置完毕. 最后单击输入法图标的选项中的首选项中的拼音模式 ...

  3. selenium通过python字典获取配置

    python字典默认的是string item={"browser " : 'webdriver.irefox()', 'url' : 'http://xxx.com'} 如果这样 ...

  4. Dubbo实践(四)设计模式

    Dubbo框架在初始化和通信过程中使用了多种设计模式,可灵活控制类加载.权限控制等功能. 工厂模式 Provider在export服务时,会调用ServiceConfig的export方法.Servi ...

  5. JNI由浅入深_7_c调用Java方法一

    1.在Java中声明方法 <span style="font-size:14px;">/** * javah -encoding utf-8 -jni com.exam ...

  6. ES6读书笔记(二)

    前言 前段时间整理了ES6的读书笔记:<ES6读书笔记(一)>,现在为第二篇,本篇内容包括: 一.数组扩展 二.对象扩展 三.函数扩展 四.Set和Map数据结构 五.Reflect 本文 ...

  7. zookeeper报错 JAVA_HOME is not set

    很多开发者安装zookeeper的时候,应该会发现到这么一个问题: JAVA_HOME is not set 好的!那么这个是什么意思呢? 就是说你的  JAVA_HOME 变量没有设定 为什么会提示 ...

  8. 10JavaScript作用域

    (作用域可访问变量的集合) 1.JavaScript 作用域 在 JavaScript 中, 对象和函数同样也是变量. 在 JavaScript 中, 作用域为可访问变量,对象,函数的集合. Java ...

  9. CentOS6安装各种大数据软件 第一章:各个软件版本介绍

    相关文章链接 CentOS6安装各种大数据软件 第一章:各个软件版本介绍 CentOS6安装各种大数据软件 第二章:Linux各个软件启动命令 CentOS6安装各种大数据软件 第三章:Linux基础 ...

  10. 嵌入式C语言自我修养 06:U-boot镜像自拷贝分析:section属性

    6.1 GNU C 的扩展关键字:attribute GNU C 增加一个 __atttribute__ 关键字用来声明一个函数.变量或类型的特殊属性.声明这个特殊属性有什么用呢?主要用途就是指导编译 ...