zoukankan      html  css  js  c++  java
  • 一起C语言中程序时序问题的排查过程

    【文章摘要

           对于由多个模块协同工作的软件来说,程序处理的时序是很重要的。当消息处理的顺序出现混乱时,程序就会出现异常。

           本文基于作者的实际项目经验。对软件模块之间的时序问题进行了具体的分析,为相关软件问题的分析及解决提供了故意的參考。

    【关键词

           C语言  时序  模块  开发  消息

     

    一、问题描写叙述

           在某软件版本号中,有两个模块(模块A与模块B)之间要进行通信。

    通信链路建立起来之后。模块A向模块B发消息,消息中携带了用户号码及序列号。在消息发送成功之后,模块A依照序列号将用户号码存放到一个全局变量中。

           模块B在接收到模块A发的消息之后。解析出用户号码,并进行相关的处理。

    在处理完毕之后,模块B将用户号码及序列号原样返回给模块A。模块A先依据接收到的序列号来查找原发送的用户号码,并与接收到的模块B返回的用户号码进行比較。若用户号码同样,则进行兴许处理。

           模块A与模块B之间的通信如图1所看到的。

    图1 模块A与模块B之间的通信

     

           在该软件版本号进行自測的过程中,发现模块A发送的用户号码与模块B返回的用户号码不能匹配,故兴许流程无法继续。

           查看模块A的日志。打印的发送的用户号码和接收的用户号码是一样的。序列号也是同样的,但在用strncmp函数(用户号码变量为字符串类型)进行比較时就出现了问题。

     

    二、模块A的程序运行流程

           因为用户号码的比較是在模块A中完毕的,因此这里主要关注模块A的程序运行流程。

           模块A的程序运行流程如图2所看到的:

    图2 模块A的程序运行流程

           从图2能够看出。在模块A与模块B的消息交互过程中,时序显得很的重要。假设消息的处理顺序未定义好。就会出现模块A程序异常终止的情况。

     

    三、问题原因初步分析

           为了确定发送的用户号码和接收的用户号码是否真的不一样,我们在对两个号码进行比較的程序语句之前加了具体的日志。想要打印出发送的用户号码、序列号和接收的用户号码、序列号。

           日志加好之后,我们又一次运行了程序,发现接收的用户号码和序列号是正确的,而发送的用户号码和序列号打印出来的是空值。

           怎么会这样呢?难道在发送的时候没有将用户号码和序列号复制到全局变量中去?

           我们又在拷贝发送用户号码和序列号的程序语句之后加了日志,想要打印出发送的用户号码和序列号的值。

    又一次运行程序之后。发现发送的用户号码和序列号是正确的。看来拷贝还是成功了的。

           通过以上的分析,能够基本确定拷贝和解析都没有问题。看来可能是处理时序导致了用户号码不能匹配的问题。

     

    四、问题定位

           我们又将日志具体地查看了一遍,发现了一个奇怪的现象,那就是日志中打印出的接收模块B返回消息的时间要比拷贝用户号码及序列号的时间早。

           为什么呢?我们对比查看了一下代码。发如今将消息发送到模块B之后,模块A休眠了一段时间之后再进行消息的拷贝。而模块B在极短的时间之内就返回了消息,此时模块A还处在休眠期。没有来得及将消息复制到全局变量中。

           难道就是模块A休眠时间惹的祸?为了验证我们的猜想,我们直接将运行休眠的代码凝视掉了来进行測试。程序又一次运行之后,再查看日志,发现一切正常了。没有打印出模块A发送的用户号码与模块B返回的用户号码不能匹配的信息,并且模块A的兴许流程也都运行到了。

    看来真是这个休眠时间闯祸了。

           确实是这种,模块B返回消息的时间极短,这样当在与全局变量中的用户号码进行比較时,事实上是一个字符串类型的用户号码在与一个空值进行比較,当然会出现故障。

    这也与发送的用户号码和序列号打印出来的是空值的事实相吻合。

           既然真相已经大白。我们就着手改动代码,将模块A中依照序列号拷贝用户号码到一个全局变量的代码放到了发送消息到模块B的代码之前,保留模块A休眠的代码。又一次对改动后的程序进行了測试,一切就OK了。

     

    五、总结

            在本次时序问题的过程排查中,主要依靠程序日志来定位问题。

            通过本次问题排查。我们总结出的经验有下面几个:

            (1) 详尽的日志有助于问题的定位。为了更清楚地了解问题出现的位置。我们能够在程序的关键语句处加入上一些測试日志。供分析所用。

            (2) 在消息处理顺序很重要的程序中,一定要理清程序运行的前后关系。防止流程“越位”的情况发生。

            (3) 在排查问题的过程中,不要放过不论什么一个蛛丝马迹,要及时验证自己的想法。多对程序进行測试。

           是程序就会有bug,因此,我们不要对程序中出现的问题耿耿于怀。要掌握排查问题的方法,这样才干够做到“以不变应万变”。通过解决不同的问题。我们才干得到锻炼,我们的开发能力才会得到提高。

     

     

    (本人微博:http://weibo.com/zhouzxi?

    topnav=1&wvr=5,微信号:245924426,欢迎关注。)

  • 相关阅读:
    记一下后续要看的点
    vue 封装request.js
    shuf命令简单用法
    Redis string 字符串
    Redis 事务操作
    Redis Zset 有序集合
    php操作redis的一些基本操作
    pytest自动化测试入门介绍
    idea&myeclipse 自动生成serialVersionUID
    leetCode1104. 二叉树寻路(medium)
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5185844.html
Copyright © 2011-2022 走看看