一起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 ...
随机推荐
- android应用Dialog跳转到Activity
public void back(Context context){ intent = new Intent(); intent.setClass(context, IBookActivity.cla ...
- ORA-00845 Oracle 启不来修改 MEMORY_TARGET
1.内存减小导致Oracle启动不了 Last login: Sun Nov 4 15:09:06 2012 from 192.168.5.222 [oracle@h1 ~]$ sqlplus ...
- pxe网络安装操作系统 原理与详细过程
摘要:在实际工作中,我们经常会遇到这样的情况:想要安装Linux但是计算机不带光驱或软驱,或者是笔记本配置的非标准的软驱和光驱,如1394接口,USB接口等,在Linux安装时所引导的Linux内核一 ...
- [Unity 3D] Unity 3D 里的碰撞检测
Unity 3D里两个碰撞体之间发生碰撞可以用OnCollision族函数和OnTrigger族函数来获知和处理.Unity官方给出了两张可发生碰撞的组合表: Collision detection ...
- CentOS Linux使用crontab运行定时任务详解
参考博文: (总结)CentOS Linux使用crontab运行定时任务详解
- ZOJ 3211 Dream City DP 01背包 经典问题
题目大意:JAVAMAN 到梦幻城市旅游见到了黄金树,黄金树上每天回结出金子.已经有n棵树,JAVAMAN要停留m天,每天只能砍掉一棵树,砍掉树后就能得到树上的黄金.给定n棵树上原有的黄金a[i]和每 ...
- css如何li中选中后加上class属性js控制
<ul> <li class=""pageson"><span>1</span></li> <li> ...
- python中multiprocessing.pool函数介绍_正在拉磨_新浪博客
python中multiprocessing.pool函数介绍_正在拉磨_新浪博客 python中multiprocessing.pool函数介绍 (2010-06-10 03:46:5 ...
- poj1887 Testing the CATCHER
Testing the CATCHER Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 13968 Accepted: 5 ...
- Sereja and Bottles
http://codeforces.com/problemset/problem/315/A 题目意思是第ai的瓶子能开bi的瓶子.给你相应的数据,求无法用其他瓶子打开的数量(即需要外力). 一开始看 ...