一起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,欢迎关注。)
一起C语言中程序时序问题的排查过程的更多相关文章
- Linux中程序的编译和链接过程
1.从源码到可执行程序的步骤:预编译.编译.链接.strip 预编译:预编译器执行.譬如C中的宏定义就是由预编译器处理,注释等也是由预编译器处理的. 编译: 编译器来执行.把源码.c .S编程机器码. ...
- 故障案例 | 主从复制环境中tokudb引擎报错排查过程
欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 0 ...
- 详解Go语言中的屏蔽现象
在刚开始学习Go语言的过程中,难免会遇到一些问题,尤其是从其他语言转向Go开发的人员,面对语法及其内部实现的差异,在使用Go开发时也避免不了会踩"坑".本文主要针对Go设计中的屏蔽 ...
- 【ZZ】C 语言中的指针和内存泄漏 & 编写高效的C程序与C代码优化
C 语言中的指针和内存泄漏 http://www.ibm.com/developerworks/cn/aix/library/au-toughgame/ 本文讨论了几种在使用动态内存分配时可以避免的陷 ...
- C语言中调用运行python程序
C语言中调用运行python程序: Python代码如下: 创建test.py. #!/usr/bin/python3 #test.py import sys x = ]) print x*x 注意: ...
- C语言中的可变参数函数的浅析(以Arm 程序中的printf()函数实现为例) .
我们在C语言编程中会遇到一些参数个数可变的函数,一般人对它的实现不理解.例如Printf(): Printf()函数是C语言中非常常用的一个典型的变参数函数,它 的原型为: int printf( c ...
- JAVA语言中的修饰符
JAVA语言中的修饰符 -----------------------------------------------01--------------------------------------- ...
- Java语言中的面向对象特性总结
Java语言中的面向对象特性 (总结得不错) [课前思考] 1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类? 2. 面向对象编程的特性有哪三个?它们各自又有哪些特性? 3. 你知 ...
- 在C语言中利用PCRE实现正则表达式
1. PCRE简介 2. 正则表达式定义 3. PCRE正则表达式的定义 4. PCRE的函数简介 5. 使用PCRE在C语言中实现正则表达式的解析 6. PCRE函数在C语言中的使用小例子 1. P ...
随机推荐
- vs2010 条件断点 has changed是什么意思?
在vs2010 断点设置 condition里,有2个选项可以选择: 一个是true,另个是has changed,true好理解,如果表达式为真则停止.但是has changed是什么意思.看了官网 ...
- asp.net从客户端检测到有潜在危险的Request.Form 值
asp.net开发中,经常遇到“从客户端检测到有潜在危险的Request.Form 值”错误提示,很多人给出的解决方案是: 1.web.config文档<system.web>后面加入这一 ...
- 基于visual Studio2013解决C语言竞赛题之0302字符数出
题目 解决代码及点评 根据题目要求,只要根据用户输入的字母,判断字母之后,给出相应的输出即可 在以下代码中,f32函数实现了该功能,通过if条件判断语句 #include <stdio.h ...
- 解决JSP中,类无法被编译的问题(XX cannot be resolved to a type)
错误调试解析: An error occurred at line: XX in the jsp file: /XX.jsp XX cannot be resolved to a type 解决方法: ...
- Java数据类型BooleanDemo
- RGB,CMYK,HSB各种颜色表示的转换 C#语言
Introduction Why an article on "colors"? It's the same question I asked myself before writ ...
- NYoj-街区最短路径问题
街区最短路径问题 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描写叙述 一个街区有非常多住户,街区的街道仅仅能为东西.南北两种方向. 住户仅仅能够沿着街道行走. 各个街道之 ...
- PHP - 继承 - 子类使用父类方法
<?php class ShopProduct { private $FirstName; private $LastName; private $Title; private $Price; ...
- iOS开发中NSDate时间戳的转换--
NSTimeInterval time =(NSTimeInterval )[model.day floatValue]; NSDate *date = [NSDate dateWithTimeInt ...
- 写一方法计算实现任意个整数之和.在主调函数中调用该函数,实现任意个数之和。(使用params参数)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...