免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2859 | 回复: 7

[C] realloc会导致coredump吗? [复制链接]

论坛徽章:
0
发表于 2008-09-23 11:27 |显示全部楼层
20可用积分
大家好,最近在忙一个ftp程序,底层是我们部门一个高手写的,现在有个问题,就是在从服务器端取得文件列表时,有很小的机率会产生coredump
一般情况下运行两三天就会出现,当出现这个问题时,FPF_FtpList连返回都没有就直接退出了。代码在下面,我看了下,估计问题出在realloc上,但是
不知道realloc会不会导致这种问题,哎,这种出现机率很小的问题最难调试了。请大家帮忙看一下。下面代码比较长,请大家主要观注一下里面的while
循环应该就行了。先谢过了!






int FPF_FtpList(FPT_FTP* ftp, const char* lpszPathName, bool bIsFullList, FPT_FTPLIST** ppFtpList)
{
        bool complete = false;
        char szCommand[256];
        int type = ftp->nTransferType;
        int list_count = 0;
        char list_string[512];
        int max_len = 64;
       
        FPF_FtpCloseList(ftp);
        if (type!=FPD_TypeAscii)
                FPF_FtpSetTransferType(ftp, FPD_TypeAscii);
        if (!FPF_FtpInitDataChunnel(ftp))
        {
                FPF_SockClose(ftp->DataChunnel);
                if (type!=FPD_TypeAscii)
                        FPF_FtpSetTransferType(ftp, type);
                strcpy(ftp->szErrorMessage, "Failed to init data chunnel\n";
                return -1;
        }
        if (bIsFullList && strncmp(ftp->strSystemType, "UNIX", 4)==0)
        {
                if (!lpszPathName || !*lpszPathName)
                        strcpy(szCommand, "LIST";
                else
                        sprintf(szCommand, "LIST %s", lpszPathName);
        }else
        {
                if (!lpszPathName || !*lpszPathName)
                        strcpy(szCommand, "NLST";
                else
                        sprintf(szCommand, "NLST %s", lpszPathName);
                bIsFullList = false;
        }
        if (!FPF_FtpSendCommand(ftp, szCommand) ||
                (ftp->nReplyCode/100!=PRELIM && ftp->nReplyCode/100!=COMPLETE))
        {
                FPF_SockClose(ftp->DataChunnel);
                if (type!=FPD_TypeAscii)
                        FPF_FtpSetTransferType(ftp, type);
                strcpy(ftp->szErrorMessage, "Failed to send command 'LIST'\n";
                return -1;
        }
        if (ftp->nReplyCode/100==COMPLETE)
                complete = true;
        if (!FPF_FtpBuildDataChunnel(ftp))
        {
                FPF_SockClose(ftp->DataChunnel);
                FPF_FtpGetReply(ftp);
                if (type!=FPD_TypeAscii)
                        FPF_FtpSetTransferType(ftp, type);
                strcpy(ftp->szErrorMessage, "Failed to build data chunnel\n";
                return -1;
        }
        memset(list_string, 0, sizeof(list_string));
        if (ftp->pFtpList)
        {
                free(ftp->pFtpList);
                ftp->pFtpList = NULL;
        }
        ftp->pFtpList = (FPT_FTPLIST*)malloc(max_len*sizeof(FPT_FTPLIST));
        ftp->nFtpListCount = 0;
        while(true)
        {
                char recvbuf[FTP_BUFSIZE+1];
                char *p1, *p2;
                int len;
               
                memset(recvbuf, 0, FTP_BUFSIZE+1);
                len = FPF_SockReceive(ftp->DataChunnel, recvbuf, FTP_BUFSIZE);
                if (len<=0 || len>FTP_BUFSIZE)
                {
                        FPF_SockClose(ftp->DataChunnel);
                        break;
                }
#ifdef _DEBUG
                printf(recvbuf);
#endif
                /*printf("FPF_FtpList  recvbuf=%s \n", recvbuf);*/
                p1 = recvbuf;
                p2 = list_string+strlen(list_string);
                while(*p1)
                {
                        if(*p1!='\n')
                                *p2++ = *p1;
                        else
                        if (strlen(list_string)<5
                        {
                                memset(list_string, 0, sizeof(list_string));
                                p2 = list_string;
                        }else
                        {
                                if (ftp->nFtpListCount==max_len)
                                {
                                        FPT_FTPLIST *pList;
                                        max_len *= 2;
                                        pList = (FPT_FTPLIST*)realloc(ftp->pFtpList, max_len*sizeof(FPT_FTPLIST));
                                        ftp->pFtpList = pList;
                                }
                               
                                memset(&(ftp->pFtpList[ftp->nFtpListCount]), 0, sizeof(ftp->pFtpList[ftp->nFtpListCount]));
                               
                                FPF_GetFtpListInfo(&(ftp->pFtpList[ftp->nFtpListCount]), list_string, bIsFullList);
                               
                                /*printf("pFtpList[ftp->nFtpListCount].filename = %s ftp->nFtpListCount=%d\n", ftp->pFtpList[ftp->nFtpListCount].filename, ftp->nFtpListCount);                       
                                */
                                        ftp->nFtpListCount++;
                                        memset(list_string, 0, sizeof(list_string));
                                        p2 = list_string;
                                }
                       
                        p1++;
                }
        }

        if (complete || (FPF_FtpGetReply(ftp) && ftp->nReplyCode/100==COMPLETE))
        {
                if (type!=FPD_TypeAscii)
                        FPF_FtpSetTransferType(ftp, type);
                *ppFtpList = ftp->pFtpList;
       /* printf("-FPF_FtpList() ,%s\n",lpszPathName);*/
                return ftp->nFtpListCount;
        }
        free(ftp->pFtpList);
        ftp->pFtpList = NULL;
        strcpy(ftp->szErrorMessage, ftp->szReplyString);
        if (type!=FPD_TypeAscii)
                FPF_FtpSetTransferType(ftp, type);
        return -1;
}

最佳答案

查看完整内容

malloc和realloc失败时返回的指针为NULL,严谨的做法应该检查malloc和realloc返回指针是否为NULL。不为NULL才继续往下处理,否则应该报错并返回。

论坛徽章:
4
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11IT运维版块每日发帖之星
日期:2016-08-11 06:20:00IT运维版块每日发帖之星
日期:2016-08-15 06:20:00
发表于 2008-09-23 11:27 |显示全部楼层

回复 #1 huangbt_unix 的帖子

malloc和realloc失败时返回的指针为NULL,严谨的做法应该检查malloc和realloc返回指针是否为NULL。不为NULL才继续往下处理,否则应该报错并返回。

论坛徽章:
0
发表于 2008-09-23 11:30 |显示全部楼层
补充一下,
FPF_FtpBuildDataChunnel()函数用来建立到服务器的数据通道
FPF_SockReceive()函数调用recv函数用来接收数据

论坛徽章:
4
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11IT运维版块每日发帖之星
日期:2016-08-11 06:20:00IT运维版块每日发帖之星
日期:2016-08-15 06:20:00
发表于 2008-09-23 11:36 |显示全部楼层

回复 #1 huangbt_unix 的帖子

对coredump后生成的core文件用gdb查看,可以看到coredump时的调用堆栈。
用gdb定位是最直接最方便的了。

论坛徽章:
0
发表于 2008-09-23 14:05 |显示全部楼层
有可能会出现coredump的情况,我以前写过一个测试程序,就是因为realloc造成程序的coredump,但在不同的内核版本上会有不同的结果,我记得好像是在redhat 7。3上没有问题。

楼主可以试一下!

论坛徽章:
0
发表于 2008-09-23 14:06 |显示全部楼层
realloc 改变内存块的大小。你可以按你的需要来扩大或缩小内存块的大小。注意,试图存取你已经分配过的内存以外的空间将会导致core dump ...

论坛徽章:
0
发表于 2008-09-23 14:25 |显示全部楼层
好谢谢大家啊,我先去调试一下!

论坛徽章:
0
发表于 2008-09-23 15:34 |显示全部楼层
另外提醒下,看多线程程序的core文件一定切到单个线程去看看,以前粗心吃拉大亏,其它线程引起的core dump,没切换线程看浪费拉很多时间。不过你的程序似乎是但线程。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP