windows中Read函数引发数据异常的问题

【摘要】

  在Window C/S开发中少不了客户端与服务端数据通信的情况,每当客户端从服务端获取数据时会将数据读到本地本件或缓存中,例如通过CInternetFile类的Read函数会将网卡缓存中的数据读入到制定的缓存中;在某APP通讯录中会很频繁地用到该函数去读取数据,然而由于当初没有细究该函数的使用情况,会意想不到地造成了客户端UI显示的内容异常,比如读取xml格式的内容时出现多余的字符串或者显示的内容为空。为此,本文将结合该函数的源码和MSDN资料以及实验结果来说明该函数的正确使用方法。

【关键字】

Windows、CInternetFile、Read

【类别】

大分类:软件;    小分类:代码优化

一、引出问题

  在某APP中查看组织通讯录时有的成员节点或者部门节点有时候会出现多余的字符串或者为空信息,当出现该情况时刷新一下数据又正常了;后续该现象复现的频率就很高了,几乎每次都会发生了。接下来,就针对该情况做数据分析。

二、发现问题

  由于该模块的数据量比较大,单步调试的话不好弄,只能通过添加打印日志来跟踪。首先,在数据显示之前将名称、职位等信息打印出来,当出现该异常时取出日志,发现显示的数据本身就有问题,接着对比一下数据库里的内容,发现数据库里存的数据也是异常数据,这个时候就需要在解析数据那块添加打印日志了,当初发现数据解析模块没有对局部变量进行初始化操作,想当然地以为是未初始化引起的,但是当对相关变量初始化操作后进行试验,该异常情况依旧出现,所以为初始化操作不是问题的原因;这个时候又开始怀疑是数据解析方法的问题,但是逆推思想推翻了该猜疑,要是是数据解析的方法有问题的话,那么所有的数据显示会异常,而不是只有少数部分数据异常;既然排除了数据解析方面,那么在数据解析之前对数据进行打印,后来实验发现确实是输入的数据有问题;而这个数据的来源是从另一个线程发送过来的,所以只能去数据源的线程查找问题的根源了。

三、找出原因

  通过阅读代码流程可知数据的来源于CInternetFile::Read()函数获取到的数据,代码如下:

string strHtml = "";

char tChars[1024+1] = {0};

while ((pFile->Read((void*)tChars, 1024)) > 0)

{

strHtml += tChars;

memset(tChars, 0, 1024 + 1);  

}

  初步看着这代码,觉得是没啥问题的,每次读取到的数据放在tChars数组里,下次读取数据之前都会置零处理,这样看似完美的流程是不会被怀疑的,可事实就是让人陷阱这个“美人计”中,导致数据异常。通过MSDN资料了解到,Read()函数第一个参数用于存放读取到的数据,第二个参数为每次读取数据的长度,它的返回值为实际读取到的数据。到此,对问题有点眉头了,也就是说Read函数第一个参数存储的是数据内容,其长度为第二个参数值;当第二个参数值和该函数的返回值不相等时,那么第一参数存储的内容就有一些内容时多余的,假设第二个参数值为InputValue,返回值为OutputValue,那么tChars数组中存有(InputValue—OutputValue)个多余的字符,并且是在数组的后面。带着这个疑惑,进入Read()函数源码分析,发现该函数调用的是InternetReadFile()函数,此函数最后一个参数就是实际读取数据的长度,为了证实我们对Read()函数第二个参数和返回值不相等的假设,那么就在该处添加断点进行调试。最后,通过实验证实了上述假设,InternetReadFile()函数返回的实际数据长度与Read()函数第二个参数值有时候会不相等。此外,通过实验发现一个有趣的问题,就是Read()函数读取到的数据若是存有多余的字符或者字符串的话,那这些多余的字符或者字符串就是Read()函数读取到的有效数据内容最后字符或字符串的重复。现在问题缘由被找到了,接下来就如何解决问题了,请看后续部分。

四、解决问题

  既然Read()函数读取到内容有两个数据长度值,那么我们就采用实际数据长度值即可,将每次读取到的数据再进行一次拷贝操作即可,方法如下:

string strHtml = "";

char tChars[1024 + 1] = {0};

char tCharsTmp[1024  + 1] = {0};

while (nReadSize > 0)

{

nReadSize = 0;

memset(tChars, 0, 1024  + 1);  

memset(tCharsTmp, 0, 1024  + 1);  

nReadSize = pFile->Read((void*)tCharsTmp, 1024);

memcpy(tChars, tCharsTmp, nReadSize);

strHtml += tChars;

}

或者

while (nReadSize > 0)

{

nReadSize = pFile->Read((void*)tCharsTmp, 1024);

strHtml.assign(tCharsTmp, 0, nReadSize);

}

  通过该方式的修改后进行试验操作,没有发现组织通讯录中存在数据显示异常的问题了;因此,问题得解。

五、得出结论

  在引用此类API函数时最好要考虑到其数据的实际长度值,然后通过其实际的数据长度来拷贝出新的一份数据,这样可以去除原有数据中多余的内容。

------20191228闪??

原文地址:https://www.cnblogs.com/bien94/p/12113147.html

时间: 2024-10-26 06:53:36

windows中Read函数引发数据异常的问题的相关文章

Windows中openProcess函数返回ERROR_ACCESS_DENIED的解决方法

辛辛苦苦开始了创业,好不容易见到了天使投资人,如何去打动明星投资人?如何能拿到那一笔"救命"钱?看徐小平.雷军这样说. 1. 天使投资人偏爱投什么样的创业者? 雷军:你有强烈的渴望做成一件伟大的事情,并且能让投资者相信你能做得成这件事情.掏自己的钱创业是创业成功率最高的一种,因为在那一瞬间你重视了,你花的每一分钱都是自己的血汗钱和别人的血汗钱,不会轻松把别的投资人的钱打水漂. 曾李青:我们体系内投了好几家公司,发现我们投资成功的公司要么是有做大公司的成功经验,要么是名校毕业.好学校不一

关于MATLAB中xlswrite函数写数据出现服务器异常情况的解决办法

在网上找了半天解决办法,也没有找到,在此共享我自己的一个问题,不具有普遍性,仅作参考! 问题描述:MATLAB调用xlsread函数出现问题,第一次运行的时候,出现服务器异常,再次运行能够正常读取数据: 在调用xlswrite函数时,一直出现服务器异常状况,不能将数据写入excel表格中. 问题关键:不是MATLAB的原因,问题出在excel软件上! 问题解决:xlswrite函数在调用时会占用excel的com端口,所以要保证在调用时这个端口是开放的,也就是没有被其他程序占用.打开excel(

JavaScript中一个函数引发的血案

规则: 1.所有的对象都有__proto__属性,指向他构造函数的原型 2.函数具有prototype属性,指向该函数的prototype 3.函数也是对象,所以函数也有__proto__属性,指向构造函数的原型,其构造函数即为Function函数 4.所有的函数都是Function的实例 5.所有函数的原型的__proto__都是Object的一个实例 6.内置函数的构造函数是一个匿名函数,且没有prototype 如 Function,Array,Object 7.JavaScript高级程

在MS单元测试中引发期望异常

首先准备一个引发异常的方法. 1 public static void ThrowException() 2 { 3 throw new ArgumentException(); 4 } 然后在单元测试项目中,写下测试方法. [TestMethod] [ExpectedException(typeof(ArgumentException))]// 构造函数中为期望引发的异常. public void ThrowExceptionTest() { Program.ThrowException();

随笔4:报错:“System.Windows.Markup.XamlParseException”类型的第一次机会异常在 PresentationFramework.dll 中发生 其他信息: “在“System.Windows.Baml2006.TypeConverterMarkupExtension”上提供值时引发了异常。”,行号为“11”,行位置为“18”。

问题描述: “System.Windows.Markup.XamlParseException”类型的第一次机会异常在 PresentationFramework.dll 中发生 其他信息: “在“System.Windows.Baml2006.TypeConverterMarkupExtension”上提供值时引发了异常.”,行号为“11”,行位置为“18”. 解决方案: 修改图片的“属性”页的“高级”中的“生成操作”,从“内容”改为“Resource”: (1)默认 (2)更改: 原文地址:

Linux启动kettle及linux和windows中kettle往hdfs中写数据(3)

在xmanager中的xshell运行进入图形化界面 1 sh spoon.sh 新建一个job 1.往hdfs中写数据 1)linux中kettle往hdfs中写数据 双击hadoop copy files 运行此job 查看数据: 1)windows中kettle往hdfs中写数据 Windows中往power服务器中hdfs写数据 日志: 2016/07/28 16:21:14 - Version checker - OK 2016/07/28 16:21:57 - 数据整合工具-作业设计

Windows中使用MySQL 数据查询(三)

一.排序 select * from employees order by name; 字符型默认字符顺序(也就是说z永远比a大),不管大小写:如果想按编码值排序(也就是说小写永远大于大写),则使用 select * from employees order by binary name; 二.取前n条记录(n在本例中为3) select * from employees order by id limit 3; 三.日期时间函数 1.获取当前日期 select curdate(); 2.取年

通过在jquery中添加函数发送ajax请求来加载数据库数据,以json的格式发送到页面

通过在jquery中添加函数发送ajax请求来加载数据库数据,以json的格式发送到页面 从数据库中查询仓库信息,显示在下拉菜单中: 首先,引入js插件,这里使用jquery-1.8.3.js <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.8.3.js"></script> 当页面加载完成后,就应该发送ajax请求到数据库,

微信公众号支付中出现XML数据异常的问题

注意:此处是xml数据异常,不是格式异常. 层层查找后发现WxpayAPI_php_v3/lib/WxPay.Api.php中notify方法中 $xml = $GLOBALS['HTTP_RAW_POST_DATA']; 此处$xml无法取得值,我改成 $xml = file_get_contents('php://input'); 成功解决问题.