Chinaunix

标题: Free的时候Core,大伙帮我分析下,所有我能想到的方法都试过了,源码和Core内容都有 [打印本页]

作者: Hex_water    时间: 2009-11-06 18:08
标题: Free的时候Core,大伙帮我分析下,所有我能想到的方法都试过了,源码和Core内容都有
这个是一个数据同步程序里面的(ProC代码),需要从一个接口表里取出一个CLOB的数据,因为这里面的数据长度不定,所以用的是动态申请的char指针来存放取出的数据,数据是Utf8的XML报文,取出来解析之后需要释放掉,在下次循环又根据CLOB的长度重新申请一片内存。
     现在的问题是,跑几条数据之后Free就会Core,在取出来之后到解析到释放都没有改变其内容。程序大概流程如下:

select * from interface; /*从接口表取出数据,一次最多500条记录,取出来是放在一个数据里*/

for(i=0;i<500;i++)
   如果interface表指示出一条记录还需要到明细表里取的时候,就如我前面陈述的,需要动态申请一个空间,因为明细表的数据是一个CLOB类型的数据;
  取出来之后解析报文;
  解析之后就需要释放这个空间;
  (就是在这里,跑几条数据就会Core)
......


   还请各位指点一下。主机是HP-UX,ORACLE10G,malloc,free哭函数。
  
   申请的空间的地址在赋值前我打印了,解析后也打印了,释放前打印了都是一样的。程序不是一跑就Core,一般都是跑了个7-8条记录就core。

  程序代码在6楼。gdb还不会用,就会这个where。

  这个Core文件里的:

HP gdb 5.7 for HP Itanium (32 or 64 bit) and target HP-UX 11.2x.
Copyright 1986 - 2001 Free Software Foundation, Inc.
Hewlett-Packard Wildebeest 5.7 (based on GDB) is covered by the
GNU General Public License. Type "show copying" to see the conditions to
change it and/or distribute copies. Type "show warranty" for warranty/support.
..
Core was generated by `orderDealBoss'.
Program terminated with signal 11, Segmentation fault.
SEGV_MAPERR - Address not mapped to object

warning: Load module /oracle/app/oracle/product/10.0/lib/libclntsh.so.10.1 has been stripped.  
Debugging information is not available.


warning: Load module /oracle/app/oracle/product/10.0/lib/libnnz10.so has been stripped.  
Debugging information is not available.

#0  0xc00000000035db40:0 in tree_delete+0x20 () from /usr/lib/hpux64/libc.so.1
(gdb) where
#0  0xc00000000035db40:0 in tree_delete+0x20 () from /usr/lib/hpux64/libc.so.1
#1  0xc000000000358fa0:0 in real_free+0x600 () from /usr/lib/hpux64/libc.so.1
#2  0xc000000000363cf0:0 in free+0x170 () from /usr/lib/hpux64/libc.so.1
#3  0x4000000000013bd0:0 in PubLogicDeal () at orderDealBoss.cp:536
#4  0x400000000001bd70:0 in PubDealTaskOneDB () at pubOrderXml.cp:771
#5  0x400000000001b3e0:0 in PubInitTaskListOneDB () at pubOrderXml.cp:671
#6  0x40000000000155c0:0 in main () at orderDealBoss.cp:675
(gdb)

[[i] 本帖最后由 Hex_water 于 2009-11-8 00:22 编辑 [/i]]
作者: naihe2010    时间: 2009-11-07 11:23
如果真的是这个流程的话,应该是没有问题的。

另外,我觉得这种程序流程不好,还是在循环之前,申请一个“足够”大的内存,循环完了再释放吧。
作者: naihe2010    时间: 2009-11-07 11:24
在解析的过程中,是不是越界了?
作者: Hex_water    时间: 2009-11-07 14:57
原帖由 naihe2010 于 2009-11-7 11:23 发表
如果真的是这个流程的话,应该是没有问题的。

另外,我觉得这种程序流程不好,还是在循环之前,申请一个“足够”大的内存,循环完了再释放吧。




       如果在循环里我用数组的都就不会Core,但是数组就得事先定义一个大小,而CLOB字段的数据,最大可以达到4G字节,所以才改为根据CLOB字段实际长度动态申请内存空间。
       循环500次,是因我前面一次取了500条记录,每条记录有可能有明细数据,有可能没有,所以是动态申请的,如果没有明细数据就只需要4000字节就够了。
作者: Hex_water    时间: 2009-11-07 15:04
原帖由 naihe2010 于 2009-11-7 11:24 发表
在解析的过程中,是不是越界了?


   调用解析函数的时候是用另外一个char指针传进去的,而且我申请的空间比实际数据长128字节,实际数据是XML报文,解析到结束标签就不会再往后解析了,应该没有越界的。解析函数一切都正常,解析函数也不改变任何的数据。如果是解析的过程越界了,会不会直接在解析的时候就已经Core了。
作者: Hex_water    时间: 2009-11-07 15:09
char *XmlTemp=NULL;
char *XmlData=NULL;
int XmlLength=4001;
init(v_det_flag);
strncpy(v_det_flag,v_order_data[i].det_flag,1);
if (strcmp(v_det_flag,ORDERDETFLAG_Y)==0)        /*如果有明细数据*/
{
        EXEC SQL SELECT LENGTH(INTERFACE_DATA) INTO :XmlLength FROM wOrderReceiptDet WHERE ORDER_ACCEPT=:v_order_data[i].order_accept;

        XmlTemp=NULL;
        XmlTemp=(char *)malloc((XmlLength+128)*sizeof(char));
        memset(XmlTemp,'3',sizeof(char)*XmlLength+128);
        if(XmlTemp==NULL)
        {
                PRINTLOG("D[%s][%s][%d]分配内存失败\n",__FILE__,__FUNC__,__LINE__);
                continue;
        }

        EXEC SQL SELECT NVL(TRIM(INTERFACE_DATA),' ') INTO :XmlTemp FROM WORDERRECEIPTDET WHERE ORDER_ACCEPT=:v_order_data[i].order_accept;
        sqlcode=SQLCODE;
        if (sqlcode!=SQLOK)
        {
                EXEC SQL ROLLBACK;
                free(XmlTemp);
                XmlTemp=NULL;

                printlog("D[%s][%s][%d]Select wOrderReceiptDet Error,SQLCODE=[%d],SQLERRMSG=[%s]\n",__FILE__,__FUNC__,__LINE__,sqlcode,SQLERRMSG);

                continue;
        }

        strim(XmlTemp);
        XmlData=XmlTemp;
}
else
{
        XmlData=&v_order_data[i].interface_data;
}

/*解析工单*/
MsgBodyType        vMsgBodyType;
memset(&vMsgBodyType,0,sizeof(MsgBodyType));

int RecordNum=0;
v_ret=OrderParseXml(&vMsgBodyType,XmlData,v_order_data[i].order_type,XmlLength,&RecordNum);
XmlData=NULL;
if (v_ret!=0)
{
        OrderDestroyMsgBody(&vMsgBodyType);
        if(XmlTemp!=NULL)
        {
                free(XmlTemp);
                XmlTemp=NULL;
        }
        printlog("D[%s][%s][%d]Process [%s] order_accept=[%ld] OrderParseXml error[%d]\n",
                __FILE__,__FUNC__,__LINE__,i_table_label, v_order_data[i].order_accept, v_ret);

        continue;
}

if(XmlTemp !=NULL)
{
        free(XmlTemp);     /*就是在这个释放会Core,不是程序一跑就Core,一般都是跑7-8条数据就Core*/
        XmlTemp=NULL;
}


这是这块的代码,大家还有没有别的思路。

[[i] 本帖最后由 Hex_water 于 2009-11-7 20:38 编辑 [/i]]
作者: Hex_water    时间: 2009-11-07 17:19
。。。。。
作者: naihe2010    时间: 2009-11-07 17:48
原帖由 Hex_water 于 2009-11-7 14:57 发表




       如果在循环里我用数组的都就不会Core,但是数组就得事先定义一个大小,而CLOB字段的数据,最大可以达到4G字节,所以才改为根据CLOB字段实际长度动态申请内存空间。
       循环500次,是因我前 ...


我知道动态申请,我说的也是动态申请。你在500次的循环里,可能申请的最大值,在循环前就申请它,在循环里不要重要申请,对性能有好处。
但你如果一条数据有4G的话,那就不好说了。
作者: naihe2010    时间: 2009-11-07 18:08
原帖由 Hex_water 于 2009-11-7 15:09 发表
char *XmlTemp=NULL;
char *XmlData=NULL;
int XmlLength=4001;
init(v_det_flag);
strncpy(v_det_flag,v_order_data.det_flag,1);
if (strcmp(v_det_flag,ORDERDETFLAG_Y)==0)        /*如果有明细数据*/
{
        E ...



你这块代码虽然错误不少,但是最可疑的地方在
v_ret=OrderParseXml(&vMsgBodyType,XmlData,v_order_data.order_type,XmlLength,&RecordNum);
这句里的XmlLength,如果
{
        XmlData=&v_order_data.interface_data;
}
的话,就没有计算,是默认值4001。对么?
作者: Hex_water    时间: 2009-11-07 18:58
原帖由 naihe2010 于 2009-11-7 18:08 发表



你这块代码虽然错误不少,但是最可疑的地方在
v_ret=OrderParseXml(&vMsgBodyType,XmlData,v_order_data.order_type,XmlLength,&RecordNum);
这句里的XmlLength,如果
{
        XmlData=&v_order_da ...


对,因为不取明细数据的话,最多就4000字节的长度。有错误的地方还请指出来。

[ 本帖最后由 Hex_water 于 2009-11-7 19:01 编辑 ]
作者: huangwei0413    时间: 2009-11-07 19:54
原帖由 Hex_water 于 2009-11-7 15:09 发表
char *XmlTemp=NULL;
char *XmlData=NULL;
int XmlLength=4001;
init(v_det_flag);
strncpy(v_det_flag,v_order_data.det_flag,1);
if (strcmp(v_det_flag,ORDERDETFLAG_Y)==0)        /*如果有明细数据*/
{
        E ...


开始
XmlTemp=(char *)malloc((XmlLength+12*sizeof(char));
memset(XmlTemp,'3',sizeof(char)*XmlLength+12;

然后
strcat(XmlTemp,"\0";

越界!
作者: Hex_water    时间: 2009-11-07 20:41
原帖由 huangwei0413 于 2009-11-7 19:54 发表


开始
XmlTemp=(char *)malloc((XmlLength+12*sizeof(char));
memset(XmlTemp,'3',sizeof(char)*XmlLength+12;

然后
strcat(XmlTemp,"\0";

越界!


谢谢。不过问题不是在这里,这个是我为了验证它会不会越界给加是一个。
作者: gawk    时间: 2009-11-07 22:04
dbx调一下core文件看看
作者: Hex_water    时间: 2009-11-08 00:24
原帖由 gawk 于 2009-11-7 22:04 发表
dbx调一下core文件看看


已添加了gdb调试的Core内容在一楼。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2