栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

一个生产环境C++工程段错误的排查

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

一个生产环境C++工程段错误的排查

最近遇到一个C++工程段错误的问题,因日志记录有回溯栈的信息,排查比较容易,解决也不难,但过程还是值得记录的。

起因

年后第一天上班的头几分钟,运维同事发消息反馈,某一机子的一个程序每天凌晨2点准时段错误重启。随后下载并查询日志,发现是一个不怎么使用的服务出问题,当时移交时,这个服务已明确不使用了,但我不敢删除,刚好这个服务开了一个端口,恰好接收不合法数据时又不判断指针结束,从而出现了段错误。自去年部门调整接手代码至今,已发生多次疑难杂症,比如内存泄漏,比如sqlite3数据库文件被无故写入日志数据,比如这次段错误。本命年估计不太顺利。

排查及解决 代码定位

出现问题的代码示例如下:

int split_cmd(char *src, const char *separeter)
{
    char *ptrsrc = src + 1;
    int idx = 0;
    while (1)
    {
        if (*ptrsrc != ',')
        {
            ptrsrc++;
            continue;
        }
        else
        {
            *ptrsrc = 0;
            //tmpp[idx]=ptrsrc;
            if (2 == ++idx)
                break;
        }
        if (*ptrsrc == 0)
        {
            printf("error cmdn");
            return -1;
        }
    }
}

问题如下:

入参src为指针,但没有判断是否合法,而且代码中将指针直接+1,这是非法危险的。separeter本意是指定分割的字符,但并没有使用之。结束条件if (*ptrsrc != ',')过简单,段错误即发现在此处。循环使用while(1),而不是通过长度遍历。 重现问题

工程是已成型的服务,在网上找了几个 socket 调试助手,但无法连接成功,后使用 linux 的 nc 命令,发送命令如下:

printf "bad cmd" | nc 127.0.0.1 1314 

重现问题。出错代码如下:

if (*ptrsrc != ',')
        {
            ptrsrc++;
            continue;
        }
解决方法

根据上述列出的问题就能快速找到解决方法,这段代码是解析通过 socket 接收的数据,数据是有长度的,但代码并没有沿用,因为不敢对代码大改,因此只改了判断条件。如下:

int RemoteMonitor::SplitCMDbuf(char *src, const char *separeter)
{
    if (src == NULL) return -1;
 ...
    while (1)
    {
        if (*ptrsrc != '' && *ptrsrc != ',')
        {
            ptrsrc++;
            continue;
        }
        ...
    }
}

另外打印了远程机器IP和数据(十六进制格式),这样能知道是谁发了什么数据。示例代码如下:

client_len = sizeof(client_addr);
if ((client_sockfd = accept(serverfd, (struct sockaddr *)&client_addr, &client_len)) < 0)
{
    printf("accept error");
    close(serverfd);
    continue;
}
char * client_ip = inet_ntoa(client_addr.sin_addr);
// int client_port = ntohs(client_addr.sin_port);
printf( recv from client %sn", client_ip);

因开年第一天上班,因此会议比较多,但还是在晚上升级好版本运行。翌日早上观察日志,结果在2点接收到非法指令,但没有出现段错误,分析得知,是一台机器发现了 http 的 GET 请求,将信息反馈至运维同事,后未有消息。

小结

写代码这么久,对出错处理十分小心。函数体第一件事就是判断参数的合法,包括指针是否为空,数值是否在合理范围,等。

nc 命令在某些场合比较方便,比如本次调试,直接在同一机器上执行即可,不需要额外的工具。

对于 socket 的连接,个人觉得加上远程 IP 地址(或端口)会比较好,起码知道连接到哪台服务器,被哪个客户端连接。本例中就新加了客户端的 IP 的打印。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/733686.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号