﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-面对现实，超越自己-随笔分类-C++</title><link>http://www.cppblog.com/wanghaiguang/category/19459.html</link><description>逆水行舟，不进则退</description><language>zh-cn</language><lastBuildDate>Fri, 14 Nov 2014 17:02:52 GMT</lastBuildDate><pubDate>Fri, 14 Nov 2014 17:02:52 GMT</pubDate><ttl>60</ttl><item><title>(转载)推荐！国外程序员整理的 C++ 资源大全</title><link>http://www.cppblog.com/wanghaiguang/archive/2014/11/14/208873.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Fri, 14 Nov 2014 00:58:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2014/11/14/208873.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/208873.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2014/11/14/208873.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/208873.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/208873.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 标准库C++标准库，包括了STL容器，算法和函数等。C++ Standard Library：是一系列类和函数的集合，使用核心语言编写，也是C++ISO自身标准的一部分。Standard Template Library：标准模板库C POSIX library&nbsp;： POSIX系统的C标准库规范ISO C++ Standards Committee&nbsp;：C++标准委员会&nbsp...&nbsp;&nbsp;<a href='http://www.cppblog.com/wanghaiguang/archive/2014/11/14/208873.html'>阅读全文</a><img src ="http://www.cppblog.com/wanghaiguang/aggbug/208873.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2014-11-14 08:58 <a href="http://www.cppblog.com/wanghaiguang/archive/2014/11/14/208873.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>进程通信之共享内存</title><link>http://www.cppblog.com/wanghaiguang/archive/2014/04/11/206537.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Fri, 11 Apr 2014 10:37:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2014/04/11/206537.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/206537.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2014/04/11/206537.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/206537.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/206537.html</trackback:ping><description><![CDATA[<span style="color: #362e2b; font-family: Verdana; font-size: 12pt; line-height: 26px; background-color: #ffffff;">C++使用共享内存实现进程间通信</span><br style="color: #362e2b; font-family: Arial; font-size: 14px; line-height: 26px; background-color: #ffffff;" /><span style="color: #362e2b; font-family: Verdana; font-size: 12pt; line-height: 26px; background-color: #ffffff;">文件映射是一种实现进程间单向或双向通信的机制。它允许两个或多个本地进程间相互通信。为了共享文件或内存，所有的进程必须使用相同的文件映射的名字或是句柄。</span><br style="color: #362e2b; font-family: Arial; font-size: 14px; line-height: 26px; background-color: #ffffff;" /><span style="color: #362e2b; font-family: Verdana; font-size: 12pt; line-height: 26px; background-color: #ffffff;">为了实现共享文件，第一个进程先调用CreateFile方法。接下来调用CreateFileMapping方法来创建一个文件映射对象。并为文件映射指明一个句柄和名称。由于事件，信号，互斥对象和文件映射等这些内核对象都共享同一个名字空间，所以如果这个名字和其他一个对象的名称重名的话那么将创建失败。</span><br style="color: #362e2b; font-family: Arial; font-size: 14px; line-height: 26px; background-color: #ffffff;" /><span style="color: #362e2b; font-family: Verdana; font-size: 12pt; line-height: 26px; background-color: #ffffff;">为了实现共享内存，进程应首先调用CreateFileMapping函数然后在hFile参数中传入INVALID_HANDLE_VALUE宏来替代句柄。相应的文件映射对象会从系统的分页文件中获得一段内存。如果hFile参数的值是INVALID_HANDLE_VALUE，那么你在调用CreateFileMapping时必须给共享内存指定一个大小值。</span><br style="color: #362e2b; font-family: Arial; font-size: 14px; line-height: 26px; background-color: #ffffff;" /><span style="color: #362e2b; font-family: Verdana; font-size: 12pt; line-height: 26px; background-color: #ffffff;">使用共享内存或文件的进程必须使用MapViewOfFile函数或MapViewOfFileEx函数来创建一个文件视图。</span><br /><span style="font-family: Verdana; font-size: 12pt;">示例代码：</span><br /><span style="font-family: Verdana; font-size: 12pt;">服务端：</span><br /><div style="background-color: #eeeeee; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><font size="2"><span style="font-family: Verdana; font-size: 12pt;">HANDLE&nbsp;hfilemapping&nbsp;=&nbsp;NULL;</span></font><br /><span style="font-size: 12pt; color: #0000ff; font-family: Verdana;">void</span><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;CCSharedMemoryDlg::OnButton1()</span></font><br /><font size="2"><span style="font-family: Verdana; font-size: 12pt;">{</span></font><br /><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;</font><span style="font-size: 12pt; color: #008000; font-family: Verdana;">//</span><font color="#008000" size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;TODO:&nbsp;Add&nbsp;your&nbsp;control&nbsp;notification&nbsp;handler&nbsp;code&nbsp;here</span><br /></font><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;hfilemapping&nbsp;=&nbsp;CreateFileMapping(INVALID_HANDLE_VALUE,&nbsp;NULL,&nbsp;PAGE_READWRITE,&nbsp;0,&nbsp;16,&nbsp;"COMBANC_SHARE");</span></font><br /><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;</font><span style="font-size: 12pt; color: #008000; font-family: Verdana;">//</span><span style="font-size: 12pt; color: #008000; font-family: Verdana;">创建错误</span><span style="font-size: 13px; color: #008000;"><br /></span><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;</font><span style="font-size: 12pt; color: #0000ff; font-family: Verdana;">if</span><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;((hfilemapping&nbsp;==&nbsp;NULL)&nbsp;||&nbsp;(hfilemapping&nbsp;==&nbsp;INVALID_HANDLE_VALUE))</span></font><br /><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;</font><span style="font-size: 12pt; color: #008000; font-family: Verdana;">//</span><span style="font-size: 12pt; color: #008000; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;lx_invalid_sharedmemory;</span><span style="font-size: 13px; color: #008000;"><br /></span><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessageBox("error");</span></font><br /><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;</font><br /><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;</font><span style="font-size: 12pt; color: #008000; font-family: Verdana;">//</span><span style="font-size: 12pt; color: #008000; font-family: Verdana;">共享内存已经存在</span><span style="font-size: 13px; color: #008000;"><br /></span><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;</font><span style="font-size: 12pt; color: #0000ff; font-family: Verdana;">if</span><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;(GetLastError()&nbsp;==&nbsp;ERROR_ALREADY_EXISTS)</span></font><br /><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;{</span></font><br /><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessageBox("共享内存已经存在");</span></font><br /><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><span style="font-size: 12pt; color: #0000ff; font-family: Verdana;">return</span><font size="2"><span style="font-family: Verdana; font-size: 12pt;">;</span></font><br /><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;}</span></font><br /><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;BYTE&nbsp;*psize&nbsp;=&nbsp;(BYTE&nbsp;*)MapViewOfFile(hfilemapping,&nbsp;FILE_MAP_WRITE,&nbsp;0,&nbsp;0,&nbsp;</span></font><span style="font-size: 12pt; color: #0000ff; font-family: Verdana;">sizeof</span><font size="2"><span style="font-family: Verdana; font-size: 12pt;">(BYTE));</span></font><br /><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;</font><span style="font-size: 12pt; color: #0000ff; font-family: Verdana;">if</span><font size="2"><span style="font-family: Verdana; font-size: 12pt;">(psize&nbsp;==&nbsp;NULL)</span></font><br /><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;{</span></font><br /><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><span style="font-size: 12pt; color: #0000ff; font-family: Verdana;">if</span><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;(hfilemapping&nbsp;!=&nbsp;NULL)</span></font><br /><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</span></font><br /><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle(hfilemapping);</span></font><br /><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hfilemapping&nbsp;=&nbsp;NULL;</span></font><br /><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></font><br /><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><span style="font-size: 12pt; color: #0000ff; font-family: Verdana;">return</span><font size="2"><span style="font-family: Verdana; font-size: 12pt;">;</span></font><br /><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;}</span></font><br /><br /><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;CString&nbsp;sTest&nbsp;=&nbsp;"abc";</span></font><br /><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;</font><span style="font-size: 12pt; color: #0000ff; font-family: Verdana;">char</span><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;ch[16]&nbsp;=&nbsp;"COMBANC_TEST";</span></font><br /><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;memcpy(psize,sTest,sTest.GetLength());</span></font><br /><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;</font><br /><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;</font><span style="font-size: 12pt; color: #0000ff; font-family: Verdana;">if</span><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;(psize&nbsp;!=&nbsp;NULL)</span></font><br /><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;{</span></font><br /><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UnmapViewOfFile(psize&nbsp;);</span></font><br /><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;psize&nbsp;=&nbsp;NULL;</span></font><br /><font size="2"><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;}</span></font><br /><font size="2"><span style="font-family: Verdana; font-size: 12pt;">}</span></font></div><br /><span style="font-size: 12pt;">客户端：</span><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="font-size: 12pt; font-family: Verdana;">HANDLE&nbsp;hfilemapping&nbsp;=&nbsp;NULL;</span><br /><span style="color: #0000ff; font-size: 12pt; font-family: Verdana;">void</span><span style="font-size: 12pt; font-family: Verdana;">&nbsp;CTestShareMemoryDlg::OnBnClickedButton1()</span><br /><span style="font-size: 12pt; font-family: Verdana;">{</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-size: 12pt; font-family: Verdana;">//</span><span style="color: #008000; font-size: 12pt; font-family: Verdana;">&nbsp;TODO:&nbsp;Add&nbsp;your&nbsp;control&nbsp;notification&nbsp;handler&nbsp;code&nbsp;here</span><span style="color: #008000; "><br /></span><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hfilemapping&nbsp;=&nbsp;OpenFileMapping(FILE_MAP_READ,&nbsp;FALSE,&nbsp;"COMBANC_SHARE");</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-size: 12pt; font-family: Verdana;">if</span><span style="font-size: 12pt; font-family: Verdana;">&nbsp;((hfilemapping&nbsp;==&nbsp;NULL)&nbsp;||&nbsp;(hfilemapping&nbsp;==&nbsp;INVALID_HANDLE_VALUE))</span><br /><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessageBox("error");</span><br />&nbsp;<br /><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;BYTE&nbsp;*psize&nbsp;=&nbsp;(BYTE&nbsp;*)MapViewOfFile(hfilemapping,&nbsp;FILE_MAP_READ,&nbsp;0,&nbsp;0,&nbsp;</span><span style="color: #0000ff; font-size: 12pt; font-family: Verdana;">sizeof</span><span style="font-size: 12pt; font-family: Verdana;">(BYTE));</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-size: 12pt; font-family: Verdana;">if</span><span style="font-size: 12pt; font-family: Verdana;">(psize&nbsp;==&nbsp;NULL)</span><br /><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;{</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-size: 12pt; font-family: Verdana;">if</span><span style="font-size: 12pt; font-family: Verdana;">&nbsp;(hfilemapping&nbsp;!=&nbsp;NULL)</span><br /><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</span><br /><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle(hfilemapping);</span><br /><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hfilemapping&nbsp;=&nbsp;NULL;</span><br /><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-size: 12pt; font-family: Verdana;">return</span><span style="font-size: 12pt; font-family: Verdana;">;&nbsp;&nbsp;&nbsp;&nbsp;</span><br /><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;}</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-size: 12pt; font-family: Verdana;">char</span><span style="font-size: 12pt; font-family: Verdana;">&nbsp;ch[16];</span><br /><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;memcpy(ch,psize,16);</span><br /><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;MessageBox(ch);</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-size: 12pt; font-family: Verdana;">if</span><span style="font-size: 12pt; font-family: Verdana;">&nbsp;(psize&nbsp;&nbsp;!=&nbsp;NULL)</span><br /><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;{</span><br /><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UnmapViewOfFile(psize&nbsp;);</span><br /><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;psize&nbsp;=&nbsp;NULL;</span><br /><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;}</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-size: 12pt; font-family: Verdana;">if</span><span style="font-size: 12pt; font-family: Verdana;">&nbsp;(hfilemapping&nbsp;!=&nbsp;NULL)</span><br /><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;{</span><br /><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle(hfilemapping);</span><br /><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hfilemapping&nbsp;=&nbsp;NULL;</span><br /><span style="font-size: 12pt; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;}</span><br /><span style="font-size: 12pt; font-family: Verdana;">}</span></div><img src ="http://www.cppblog.com/wanghaiguang/aggbug/206537.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2014-04-11 18:37 <a href="http://www.cppblog.com/wanghaiguang/archive/2014/04/11/206537.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 解析Json——jsoncpp</title><link>http://www.cppblog.com/wanghaiguang/archive/2013/12/26/205020.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Thu, 26 Dec 2013 07:59:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2013/12/26/205020.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/205020.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2013/12/26/205020.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/205020.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/205020.html</trackback:ping><description><![CDATA[<span style="color: #333333; font-family: Verdana; font-size: 12pt; line-height: 24px; text-indent: 28px; background-color: #ffffff;">JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式，和xml类似，本文主要对VS2008中使用Jsoncpp解析json的方法做一下记录。<br /></span><span style="color: #333333; font-family: Verdana; line-height: 26px; background-color: #ffffff; font-size: 12pt;">Jsoncpp是个跨平台的开源库，下载地址：</span><a href="http://jsoncpp.sourceforge.net/" style="font-size: 14px; color: #336699; text-decoration: none; font-family: Arial; line-height: 26px; background-color: #ffffff;"></a><a href="http://sourceforge.net/projects/jsoncpp/"><span style="font-size: 12pt; font-family: Verdana;">http://sourceforge.net/projects/jsoncpp/</span></a><span style="color: #333333; font-family: Verdana; line-height: 26px; background-color: #ffffff; font-size: 12pt;">，我下载的是v0.5.0，压缩包大约104K。</span><br /><span style="font-size: 12pt;"><br /></span><strong><span style="font-size: 12pt; font-family: Verdana;">方法一：使用</span><span style="color: #333333; font-family: Verdana; font-size: 12pt; line-height: 25.98958396911621px; background-color: #ffffff;">Jsoncpp生成的lib文件</span></strong><br />&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #333333; font-family: Verdana; line-height: 26px; background-color: #ffffff; font-size: 12pt;">解压上面下载的</span><span style="color: #333333; font-family: Verdana; font-size: 12pt; line-height: 25.98958396911621px; background-color: #ffffff;">Jsoncpp</span><span style="color: #333333; font-family: Verdana; line-height: 26px; background-color: #ffffff; font-size: 12pt;">文件，在jsoncpp-src-0.5.0/makefiles/vs71目录里找到jsoncpp.sln，用VS2008版本编译，默认生成静态链接库。 在工程中引用，只需要包含include/json下的头文件及生成的.lib文件即可。<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #333333; font-family: Verdana; line-height: 26px; background-color: #ffffff; font-size: 12pt;">如何包含lib文件：在.cpp文件中</span><span style="font-size: 12pt; font-family: Verdana;">#pragma comment(lib."json_vc71_libmt.lib")，在工程属性中Linker下Input中Additional Dependencies写入lib文件名字（Release下为</span><span style="font-size: 12pt; font-family: Verdana;">json_vc71_libmt.lib，Debug为</span><span style="font-size: 12pt; font-family: Verdana;">json_vc71_libmtd.lib</span><span style="font-size: 12pt; font-family: Verdana;">）</span><br /><span style="font-size: 12pt; color: red;"><br /></span><span style="font-size: 12pt; color: red; font-family: Verdana;">注意：</span><span style="color: #333333; font-family: Verdana; font-size: 12pt; line-height: 25.98958396911621px; background-color: #ffffff;">Jsoncpp的lib工程编译选项要和VS工程中的编译选项保持一致。如lib文件工程编译选项为MT（或MTd），VS工程中也要选择MT</span><span style="color: #333333; font-family: Verdana; font-size: 12pt; line-height: 25.98958396911621px; background-color: #ffffff;">（或MTd），否则会出现编译错误问题，debug和release下生成的lib文件名字不同，注意不要看错了，当成一个文件来使用（我就犯了这个错误）。<br /><br /></span><strong><span style="font-size: 12pt; font-family: Verdana;">方法二：使用</span><span style="color: #333333; font-family: Verdana; font-size: 12pt; line-height: 25.98958396911621px; background-color: #ffffff;">Jsoncpp包中的.cpp</span><span style="background-color: #ffffff; font-size: 12pt; font-family: Verdana;">和</span></strong><span style="color: #333333; font-family: Verdana; font-size: 12pt; line-height: 25.98958396911621px; background-color: #ffffff;"><strong>.h文件</strong><br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #333333; font-family: Verdana; line-height: 26px; background-color: #ffffff; font-size: 12pt;">解压上面下载的</span><span style="color: #333333; font-family: Verdana; font-size: 12pt; line-height: 25.98958396911621px; background-color: #ffffff;">Jsoncpp</span><span style="color: #333333; font-family: Verdana; line-height: 26px; background-color: #ffffff; font-size: 12pt;">文件，把</span><span style="color: #333333; font-family: Verdana; font-size: 12pt; line-height: 25.98958396911621px; background-color: #ffffff;">jsoncpp-src-0.5.0文件拷贝到工程目录下，</span><span style="color: #333333; font-family: Verdana; line-height: 26px; background-color: #ffffff; font-size: 12pt;">将</span><span style="font-size: 12pt; font-family: Verdana;">jsoncpp-src-0.5.0\jsoncpp-src-0.5.0\include\json</span><span style="font-size: 12pt; font-family: Verdana;">和</span><span style="font-size: 12pt; font-family: Verdana;">jsoncpp-src-0.5.0\jsoncpp-src-0.5.0\src\lib_json</span><span style="background-color: #ffffff; color: #333333; font-family: Verdana; font-size: 12pt; line-height: 26px;">目录里的文件包含到VS工程中，在VS工程的属性C/C++下General中</span><span style="font-size: 12pt; font-family: Verdana;">Additional Include Directories</span><span style="background-color: #ffffff; color: #333333; font-family: Verdana; font-size: 12pt; line-height: 26px;">包含头文件目录</span><span style="font-size: 12pt; font-family: Verdana;">.\jsoncpp-src-0.5.0\include</span><span style="background-color: #ffffff; color: #333333; font-family: Verdana; font-size: 12pt; line-height: 26px;">。在使用的cpp文件中</span><span style="background-color: #ffffff; color: #333333; font-family: Verdana; font-size: 12pt; line-height: 26px;">包含json头文件即可，如：</span><span style="font-size: 12pt; font-family: Verdana;">#include "json/json.h"</span><span style="background-color: #ffffff; color: #333333; font-family: Verdana; font-size: 12pt; line-height: 26px;">。将</span><span style="font-size: 12pt; font-family: Verdana;">json_reader.cpp、</span><span style="font-size: 12pt; font-family: Verdana;">json_value.cpp和</span><span style="font-size: 12pt; font-family: Verdana;">json_writer.cpp三个文件的Precompiled Header属性设置为</span><span style="font-size: 14px; font-family: Verdana;"><strong>Not Using Precompiled Headers</strong>，</span><span style="font-size: 12pt; font-family: Verdana;">否则编译会出现错误。</span><span style="font-size: 14px;"><br /></span><span style="color: #333333; font-family: Arial; font-size: 13.333333969116211px; line-height: 25.98958396911621px; background-color: #ffffff;"><br /></span><p style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14px; line-height: 26px; background-color: #ffffff;"><strong style="font-size: 12pt; font-family: Verdana;">jsoncpp 使用详解</strong></p><p style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14px; line-height: 26px; background-color: #ffffff;"><span style="font-size: 12pt; font-family: Verdana;">jsoncpp 主要包含三种类型的 class：Value、Reader、Writer。jsoncpp 中所有对象、类名都在 namespace Json 中，包含 json.h 即可。</span></p><p style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14px; line-height: 26px; background-color: #ffffff;"><span style="font-size: 12pt; font-family: Verdana;">Json::Value 只能处理 ANSI 类型的字符串，如果 C++ 程序是用 Unicode 编码的，最好加一个 Adapt 类来适配。</span></p><span style="color: #333333; font-family: Arial; font-size: 13.333333969116211px; line-height: 25.98958396911621px; background-color: #ffffff;"><br /></span><span style="color: #333333; font-family: Verdana; font-size: 12pt; line-height: 25.98958396911621px; background-color: #ffffff;">下面是从网上找的代码示例：<br /></span><span style="color: #333333; font-family: Verdana; font-size: 12pt; line-height: 26px; background-color: #ffffff;">1. 从字符串解析json</span><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="font-family: Verdana;">&nbsp; &nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Verdana;">const</span>&nbsp;<span style="color: #0000ff; font-family: Verdana;">char</span><span style="font-family: Verdana;">*&nbsp;str&nbsp;=&nbsp;"{\"uploadid\":&nbsp;\"UP000000\",\"code\":&nbsp;100,\"msg\":&nbsp;\"\",\"files\":&nbsp;\"\"}";&nbsp;&nbsp;</span><br /><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;Json::Reader&nbsp;reader;&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;Json::Value&nbsp;root;&nbsp;&nbsp;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">if</span><span style="font-family: Verdana;">&nbsp;(reader.parse(str,&nbsp;root))&nbsp;&nbsp;</span><span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;reader将Json字符串解析到root，root将包含Json里所有子元素&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::</span><span style="color: #0000ff; font-family: Verdana;">string</span><span style="font-family: Verdana;">&nbsp;upload_id&nbsp;=&nbsp;root["uploadid"].asString();&nbsp;&nbsp;</span><span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;访问节点，upload_id&nbsp;=&nbsp;"UP000000"&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">int</span><span style="font-family: Verdana;">&nbsp;code&nbsp;=&nbsp;root["code"].asInt();&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;访问节点，code&nbsp;=&nbsp;100&nbsp;</span><span style="color: #008000; "><br /></span><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;</span></div><span style="color: #333333; font-family: Verdana; font-size: 12pt; line-height: 26px; background-color: #ffffff;">2. 从文件解析json</span><span style="color: #333333; font-family: Arial; font-size: 13px; line-height: 26px; background-color: #ffffff;"><br /></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff; font-family: Verdana;">int</span><span style="font-family: Verdana;">&nbsp;ReadJsonFromFile(</span><span style="color: #0000ff; font-family: Verdana;">const</span>&nbsp;<span style="color: #0000ff; font-family: Verdana;">char</span><span style="font-family: Verdana;">*&nbsp;filename)&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">{&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;Json::Reader&nbsp;reader;</span><span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;解析json用Json::Reader&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;Json::Value&nbsp;root;&nbsp;</span><span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;Json::Value是一种很重要的类型，可以代表任意类型。如int,&nbsp;string,&nbsp;object,&nbsp;array<img src="http://www.cppblog.com/Images/dot.gif" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;std::ifstream&nbsp;</span><span style="color: #0000ff; font-family: Verdana;">is</span><span style="font-family: Verdana;">;&nbsp;&nbsp;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">is</span><span style="font-family: Verdana;">.open&nbsp;(filename,&nbsp;std::ios::binary&nbsp;);&nbsp;&nbsp;&nbsp;&nbsp;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">if</span><span style="font-family: Verdana;">&nbsp;(reader.parse(</span><span style="color: #0000ff; font-family: Verdana;">is</span><span style="font-family: Verdana;">,&nbsp;root,&nbsp;FALSE))&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::</span><span style="color: #0000ff; font-family: Verdana;">string</span><span style="font-family: Verdana;">&nbsp;code;&nbsp;&nbsp;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">if</span><span style="font-family: Verdana;">&nbsp;(!root["files"].isNull())&nbsp;&nbsp;</span><span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;访问节点，Access&nbsp;an&nbsp;object&nbsp;value&nbsp;by&nbsp;name,&nbsp;create&nbsp;a&nbsp;null&nbsp;member&nbsp;if&nbsp;it&nbsp;does&nbsp;not&nbsp;exist.&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;code&nbsp;=&nbsp;root["uploadid"].asString();&nbsp;&nbsp;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;code&nbsp;=&nbsp;root.</span><span style="color: #0000ff; font-family: Verdana;">get</span><span style="font-family: Verdana;">("uploadid",&nbsp;"null").asString();</span><span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;访问节点，Return&nbsp;the&nbsp;member&nbsp;named&nbsp;key&nbsp;if&nbsp;it&nbsp;exist,&nbsp;defaultValue&nbsp;otherwise.&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">int</span><span style="font-family: Verdana;">&nbsp;file_size&nbsp;=&nbsp;root["files"].size();&nbsp;&nbsp;</span><span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;得到"files"的数组个数&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">for</span><span style="font-family: Verdana;">(</span><span style="color: #0000ff; font-family: Verdana;">int</span><span style="font-family: Verdana;">&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;file_size;&nbsp;++i)&nbsp;&nbsp;</span><span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;遍历数组&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Json::Value&nbsp;val_image&nbsp;=&nbsp;root["files"][i]["images"];&nbsp;&nbsp;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">int</span><span style="font-family: Verdana;">&nbsp;image_size&nbsp;=&nbsp;val_image.size();&nbsp;&nbsp;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">for</span><span style="font-family: Verdana;">(</span><span style="color: #0000ff; font-family: Verdana;">int</span><span style="font-family: Verdana;">&nbsp;j&nbsp;=&nbsp;0;&nbsp;j&nbsp;&lt;&nbsp;image_size;&nbsp;++j)&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::</span><span style="color: #0000ff; font-family: Verdana;">string</span><span style="font-family: Verdana;">&nbsp;type&nbsp;=&nbsp;val_image[j]["type"].asString();&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::</span><span style="color: #0000ff; font-family: Verdana;">string</span><span style="font-family: Verdana;">&nbsp;url&nbsp;&nbsp;=&nbsp;val_image[j]["url"].asString();&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("type&nbsp;:&nbsp;%s,&nbsp;url&nbsp;:&nbsp;%s&nbsp;\n",&nbsp;type.c_str(),&nbsp;url.c_str());</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">is</span><span style="font-family: Verdana;">.close();&nbsp;&nbsp;</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">return</span><span style="font-family: Verdana;">&nbsp;0;&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">}&nbsp;</span></div><span style="color: #333333; font-family: Verdana; font-size: 12pt; line-height: 26px; background-color: #ffffff;">3. 向文件中插入json</span><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff; font-family: Verdana;">void</span><span style="font-family: Verdana;">&nbsp;WriteJsonData(</span><span style="color: #0000ff; font-family: Verdana;">const</span>&nbsp;<span style="color: #0000ff; font-family: Verdana;">char</span><span style="font-family: Verdana;">*&nbsp;filename)</span><br /><span style="font-family: Verdana;">{</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;Json::Reader&nbsp;reader;&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;Json::Value&nbsp;root;&nbsp;</span><span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;Json::Value是一种很重要的类型，可以代表任意类型。如int,&nbsp;string,&nbsp;object,&nbsp;array<img src="http://www.cppblog.com/Images/dot.gif" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;std::ifstream&nbsp;</span><span style="color: #0000ff; font-family: Verdana;">is</span><span style="font-family: Verdana;">;&nbsp;&nbsp;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">is</span><span style="font-family: Verdana;">.open&nbsp;(filename,&nbsp;std::ios::binary&nbsp;);&nbsp;&nbsp;&nbsp;&nbsp;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">if</span><span style="font-family: Verdana;">&nbsp;(reader.parse(</span><span style="color: #0000ff; font-family: Verdana;">is</span><span style="font-family: Verdana;">,&nbsp;root))&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Json::Value&nbsp;arrayObj;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;构建对象&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Json::Value&nbsp;new_item,&nbsp;new_item1;&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new_item["date"]&nbsp;=&nbsp;"2011-11-11";&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new_item1["time"]&nbsp;=&nbsp;"11:11:11";&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arrayObj.append(new_item);&nbsp;&nbsp;</span><span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;插入数组成员&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arrayObj.append(new_item1);&nbsp;</span><span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;插入数组成员&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">int</span><span style="font-family: Verdana;">&nbsp;file_size&nbsp;=&nbsp;root["files"].size();&nbsp;&nbsp;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">for</span><span style="font-family: Verdana;">(</span><span style="color: #0000ff; font-family: Verdana;">int</span><span style="font-family: Verdana;">&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;file_size;&nbsp;++i)&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;root["files"][i]["exifs"]&nbsp;=&nbsp;arrayObj;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;插入原json中&nbsp;</span><span style="color: #008000; "><br /></span><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::</span><span style="color: #0000ff; font-family: Verdana;">string</span>&nbsp;<span style="color: #0000ff; font-family: Verdana;">out</span><span style="font-family: Verdana;">&nbsp;=&nbsp;root.toStyledString();&nbsp;&nbsp;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;输出无格式json字符串&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Json::FastWriter&nbsp;writer;&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::</span><span style="color: #0000ff; font-family: Verdana;">string</span><span style="font-family: Verdana;">&nbsp;strWrite&nbsp;=&nbsp;writer.write(root);</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::ofstream&nbsp;ofs;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ofs.open("test_write.json");</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ofs&nbsp;&lt;&lt;&nbsp;strWrite;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ofs.close();</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">is</span><span style="font-family: Verdana;">.close();&nbsp;&nbsp;</span><br /><span style="font-family: Verdana;">}</span></div><span style="color: #333333; font-family: Arial; font-size: 13px; line-height: 26px; background-color: #ffffff;"><br /></span><span style="color: #333333; font-family: Verdana; font-size: 12pt; line-height: 26px; background-color: #ffffff;">下面是我写的</span><span style="font-size: 12pt; font-family: Verdana;">使用</span><span style="color: #333333; font-family: Verdana; font-size: 12pt; line-height: 25.98958396911621px; background-color: #ffffff;">Jsoncpp生成lib文件的工程示例：<span style="font-size: 12pt;"><a title="Jsoncpp测试代码" href="/Files/wanghaiguang/TestJsoncppCode.rar"><span style="font-family: Verdana;">Jsoncpp测试代码</span></a></span><span style="font-size: 12pt; font-family: Verdana;">，使用VS2008编译通过。</span></span><span style="color: #333333; font-family: Arial; font-size: 13.333333969116211px; line-height: 25.98958396911621px; background-color: #ffffff;"><br /></span><img src ="http://www.cppblog.com/wanghaiguang/aggbug/205020.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2013-12-26 15:59 <a href="http://www.cppblog.com/wanghaiguang/archive/2013/12/26/205020.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何调试程序的 Release 版本？(转)</title><link>http://www.cppblog.com/wanghaiguang/archive/2013/11/28/204484.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Thu, 28 Nov 2013 02:20:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2013/11/28/204484.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/204484.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2013/11/28/204484.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/204484.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/204484.html</trackback:ping><description><![CDATA[<span style="font-family: Verdana; font-size: 12pt; line-height: 19px; background-color: #ffffff;">很多时候程序的 Debug 版本运行没有任何问题，但是一旦发布 Release 版本后，运行就出错，着实让人郁闷。大家知道，VC++ 中 Release 版本是对无法对源代码进行调试的。一般的做法是在怀疑有错误的代码前后插入MessageBox 函数，在函数中显示可能导致错误的变量的值。或者插入写文件的语句，输出可能导致错误的变量的值到一个记录文件。其实，除了上面讲的这个办法之外，还有其它的途径来调试 Release 版本的。下面就结合自己的经验和网上查找的一些资料给出调试 Release 版本的两个方法：</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana; font-size: 12pt; line-height: 19px; background-color: #ffffff;"><strong>方法一、利用 *.PDB 符号文件调试 Release 版本</strong></span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana; font-size: 12pt; line-height: 19px; background-color: #ffffff;">在 VCKBASE 的在线杂志中有一篇参考文章：符号文件&#8212;&#8212;Windows 应用程序调试必备（http://www.vckbase.com/document/viewdoc/?id=1710），文章谈到了如何产生 Release 版本二进制文件对应的 PDB 文件的问题。有了 PDB 文件后，就可以调试 Release 了，方法是：</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana; font-size: 12pt; line-height: 19px; background-color: #ffffff;">1、在Project Settings里选Settings For为All Configurations。&nbsp;</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana; font-size: 12pt; line-height: 19px; background-color: #ffffff;">2、在C/C++标签中，Debug info 选 Program Database。&nbsp;</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana; font-size: 12pt; line-height: 19px; background-color: #ffffff;">3、在Link 标签中，Category选 Debug，选中Debug info 复选框和Microsoft format。&nbsp;</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana; font-size: 12pt; line-height: 19px; background-color: #ffffff;">进行了上述设置后，我们就可以像在调试版本中那样设置断点进行测试了，由于代码优化，有些变量观察不到，行的运行顺序可能也会不同。&nbsp;</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana; font-size: 12pt; line-height: 19px; background-color: #ffffff;">有一点需要注意：ASSERT宏在 Release 版本中不起作用，在 Release 版本中应该使用 VERIFY 来代替 ASSERT 进行调试。如果发行版本运行有问题，可以先禁止所有代码优化再进行调试。</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana; font-size: 12pt; line-height: 19px; background-color: #ffffff;"><strong>方法二、在需要加断点的地方添加如下汇编语句：&nbsp;</strong></span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana; font-size: 12pt; line-height: 19px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;__asm int 3&nbsp;</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana; font-size: 12pt; line-height: 19px; background-color: #ffffff;">不过调试的时候无法显示C程序，只有asm代码。&nbsp;</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana; font-size: 12pt; line-height: 19px; background-color: #ffffff;">此处 int 3 是专门用来设置断点的，是 CPU 定义的，Windows 和 DOS 下的大多数调试器都采用这种方法。</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana; font-size: 12pt; line-height: 19px; background-color: #ffffff;">本贴不断更新中，希望大家跟贴贡献出更好的调试方法。以便受益者少走弯路......<br /><br /></span><span style="font-size: 12pt;">本文转自：</span><a href="http://www.cppblog.com/mzty/archive/2006/11/19/15439.html"><span style="font-size: 12pt;">http://www.cppblog.com/mzty/archive/2006/11/19/15439.html</span></a><img src ="http://www.cppblog.com/wanghaiguang/aggbug/204484.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2013-11-28 10:20 <a href="http://www.cppblog.com/wanghaiguang/archive/2013/11/28/204484.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HOOK技术的一些简单总结（转载）</title><link>http://www.cppblog.com/wanghaiguang/archive/2013/11/08/204158.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Fri, 08 Nov 2013 00:15:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2013/11/08/204158.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/204158.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2013/11/08/204158.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/204158.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/204158.html</trackback:ping><description><![CDATA[<div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;">在Window平台上开发任何稍微底层一点的东西，基本上都是Hook满天飞， 普通应用程序如此，安全软件更是如此， 这里简单记录一些常用的Hook技术。</div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx" style="color: #4371a6; cursor: pointer;"><strong>SetWindowsHookEx</strong></a></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;">基本上做Windows开发都知道这个API， 它给我们提供了一个拦截系统事件和消息的机会， 并且它可以将我们的DLL注入到其他进程。</div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;">但是随着64位时代的到来和Vista之后的UAC机制开启，这个API很多时候不能正常工作了：</div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;">首先，32位DLL没法直接注入到64位的应用程序里面， 因为他们的地址空间完全不一样的。当然尽管没法直接注入，但是在权限范围内，系统会尽量以消息的方式让你能收到64位程序的消息事件。</div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;">其次，UAC打开的情况下低权限程序没法Hook高权限程序， 实际上低权限程序以高权限程序窗口为Owner创建窗口也会失败， 低权限程序在高权限程序窗口上模拟鼠标键盘也会失败。</div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;">有人说我们可以关闭UAC， Win7下你确实可以，但是Win8下微软已经不支持真正关闭UAC， 从这里我们也可以看到微软技术过渡的方式， 中间会提供一个选项来让你慢慢适应，最后再把这个选项关掉， UAC和Aero模式都是如此。</div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;">那么我们如何解决这些问题？</div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;">对于64位问题&nbsp;，&nbsp;解决方法是提供2个DLL，分别可以Hook32和64位程序。</div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;">对于权限问题， 解决方法是提升权限， 通过注册系统服务，&nbsp;由服务程序创建我们的工作进程。这里为什么要创建一个其他进程而不直接在服务进程里干活？ 因为Vista后我们有了Session隔离机制，服务程序运行在Session 0，我们的其他程序运行在Session 1, Session 2等， 如果我们直接在服务程序里干活，我们就只能在Session 0里工作。通过创建进程，我们可以在<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa446617(v=vs.85).aspx" style="color: #4371a6; cursor: pointer;">DuplicateTokenEx</a>后将Token的SessionID设置成目标Session，并且在<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682429(v=vs.85).aspx" style="color: #4371a6; cursor: pointer;">CreateProcessAsUser</a>时指定目标WinStation和Desktop， 这样我们就既获得了System权限，并且也可以和当前桌面进程交互了。</div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd373640(v=vs.85).aspx" style="color: #4371a6; cursor: pointer;"><strong>SetWinEventHook</strong></a></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;">很多人可能都不知道这个API， 但是这个API其实挺重要的， 看名字就知道它是Hook事件(Event)的， 具体哪些事件可以看<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd318066(v=vs.85).aspx#EVENT_MIN" style="color: #4371a6; cursor: pointer;">这里</a>.</div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;">为什么说这个API重要， 因为这个API大部分时候没有SetWindowsHookEx的权限问题， 也就是说这个API可以让你Hook到高权限程序的事件， 它同时支持进程内(<span style="line-height: 20px; color: #2a2a2a;">WINEVENT_INCONTEXT</span>)和进程外(<span style="line-height: 20px; color: #2a2a2a;">WINEVENT_OUTOFCONTEXT</span>)2种Hook方式， 你可以以进程外的方式Hook到64位程序的事件。</div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;">为什么这个API没有权限问题， 因为它是给Accessibility用的， 也就是它是给自动测试和残障工具用的， 所以它要保证有效。</div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;">我曾经看到这样一个程序，当任何程序(无论权限高低)有窗口拖动(拖标题栏改变位置或是拖边框改变大小)， 程序都能捕获到， 当时很好奇它是怎么做到的？</div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;">Spy了下窗口消息, 知道有这样2个消息：<span style="line-height: 20px; font-family: Consolas, Courier, monospace;">WM_ENTERSIZEMOVE和</span><span style="line-height: 20px; font-family: Consolas, Courier, monospace;">WM_EXITSIZEMOVE表示进入和退出这个事件， 但是那也只能获得自己的消息，其他程序的消息它是如何捕获到的？当时怀疑用的是Hook， 却发现没有DLL注入。查遍了Windows API 也没有发现有API可以查询一个窗口是否在这个拖动状态。最后发现用的是SetWinEventHook</span><span style="line-height: 20px;">的</span><span style="line-height: 20px; color: #2a2a2a;">EVENT_SYSTEM_MOVESIZESTART和</span><span style="line-height: 20px; color: #2a2a2a;">EVENT_SYSTEM_MOVESIZEEND。</span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; color: #2a2a2a;"><br /></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; color: #2a2a2a;"><strong>API Hook</strong></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px;">常见的API Hook包括2种， 一种是基于PE文件的导入表(IAT), 还有</span><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">一种是修改前5个字节直接JMP的inline Hook.</span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;"><br /></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px;">对于基于IAT的方式， 原理是PE文件里有个导入表， 代表该模块调用了哪些外部API，模块被加载到内存后， PE加载器会修改该表，地址改成外部API重定位后的真实地址， 我们只要直接把里面的地址改成我们新函数的地址， 就可以完成对相应API的Hook。《Windows核心编程》里第22章</span><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">有个封装挺好的CAPIHook类，我们可以直接拿来用。</span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px;">我曾经用API Hook来实现自动测试，见这里&nbsp;<a href="http://www.cppblog.com/weiym/archive/2012/05/03/173611.html" style="color: #4371a6; cursor: pointer;">API Hook在TA中的应用</a></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;"><br /></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">对于基于Jmp方式的inline hook, 原理是修改目标函数的前5个字节， 直接Jmp到我们的新函数。虽然原理挺简单， 但是因为用到了平台相关的汇编代码， 一般人很难写稳定。真正在项目中用还是要求稳定， 所以我们一般用微软封装好的<a href="http://research.microsoft.com/en-us/downloads/d36340fb-4d3c-4ddd-bf5b-1db25d03713d/default.aspx" style="color: #4371a6; cursor: pointer;">Detours</a>, 对于Detours的原理，这里有篇不错的文章&nbsp;</span><span style="line-height: 20px;"><a href="http://www.cnblogs.com/flying_bat/archive/2008/04/18/1159996.html" style="color: #4371a6; cursor: pointer;">微软研究院Detour开发包之API拦截技术</a>。</span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px;"><br /></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px;">比较一下2种方式：&nbsp;</span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px;">IAT的方式比较安全简单， 但是只适用于Hook导入函数方式的API。</span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px;">Inline Hook相对来说复杂点， 但是它能Hook到任何函数(API和内部函数)，但是它要求目标函数大于5字节， 同时把握好修改时机或是Freeze其他线程， 因为多线程中改写可能会引起冲突。<br /><br /><div style="line-height: normal;"><span style="line-height: 20px;">还有一种是Hook被调用模块的导出表（EAT）， 但是感觉一般用得用的不多。原理是调用模块里IAT中的函数地址是通过被调用模块的EAT获取的， 所以你只要修改了被调用模块的EAT中的函数地址，对方的调用就自然被你Hook了。但是这里有个时机问题， 就是你替换EAT表要足够早，要在IAT使用它之前才行。但是感觉这个行为是由PE加载器决定的， 一般人很难干涉， 不知道大家有什么好方法？&nbsp;</span></div><div style="line-height: normal;"><span style="line-height: 20px;"><br /></span></div><div style="line-height: normal;"><span style="line-height: 20px;">我们一般可以将IAT Hook和EAT Hook结合起来使用， 先枚举所有模块Hook IAT，这样当前已有模块的API都被你Hook了，然后再Hook EAT， 这样后续的模块也被你Hook了（</span><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">因为要通过EAT获取函数地址）。&nbsp;</span></div><div style="line-height: normal;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;"><br /></span></div><div style="line-height: normal;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">如果你只用Hook IAT而不Hook EAT, 当有新模块加载时，你要Hook它的IAT， 所以你就要Hook LoadLibrary(Ex)和GetProcAddress来拦截新模块的加载。</span><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">所以理论上感觉 Hook EAT不是很有必要， 因为单用Hook IAT已经可以解决我们所有的问题了， HOOK IAT还有一种优势是我们可以过滤某个模块不Hook，而一旦hook EAT， 它就会影响我们所有调用该函数的模块。</span></div></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px;"><br /></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px;"><strong>COM Hook</strong></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px;">Window上因为有很多开发包是以COM方式提供的(比如DirectX)， 所以我们就有了拦截COM调用的COM Hook。</span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px;">因为COM里面很关键的是它的接口是C++里虚表的形式提供的， 所以COM的Hook很多是时候其实就是虚表</span><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">（vtable）的Hook。</span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">关于C++ 对象模型和虚表可以看我这篇&nbsp;</span><span style="line-height: 20px;"><a href="http://www.cppblog.com/weiym/archive/2012/09/21/191543.html" style="color: #4371a6; cursor: pointer;">探索C++对象模型</a></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;"><br /></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">对于COMHook，考虑下面2种case：</span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;"><br /></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">一种是我们Hook程序先运行，然后启动某个游戏程序（DirectX 9）， 我们想Hook游戏的绘画内容。</span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;"><br /></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">这种方式下， 我们可以先Hook API&nbsp;</span><span style="line-height: 20px;">Direct3DCreate9， 然后我们继承于IDirect3D9， 自己实现一个COM对象返回回去， 这样我们就可以拦截到所有对该对象的操作，</span><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">为所欲为了， 当然我们自己现实的COM对象内部会调用真正的</span><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">Direct3DCreate9，封装真正的</span><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">IDirect3D9。</span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;"><br /></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">当然有时我们可能不用替代整个COM组件，我们只需要修改其中一个或几个COM函数， 这种情况下我们可以创建真正的</span><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">IDirect3D9对象后直接修改它的虚表， 把其中某些函数改成我们自己的函数地址就可以了。</span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;"><br /></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">其实ATL就是用接口替代的方式来调试和记录COM接口引用计数的次数， 具体可以看我这篇&nbsp;</span><span style="line-height: 20px;"><a href="http://www.cppblog.com/weiym/archive/2012/10/23/193701.html" style="color: #4371a6; cursor: pointer;">理解ATL中的一些汇编代码</a></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px;"><br /></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">还有一种case是游戏程序已经在运行了， 然后才启动我们的Hook进程， 我们怎么样才能Hook到里面的内容？</span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;"><br /></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">这种情况下我们首先要对程序内存有比较详细的认识， 才能思考创建出来的D3D对象的虚表位置， 从而进行Hook， 关于程序内存布局，可见我这篇&nbsp;</span><span style="line-height: 20px;"><a href="http://www.cppblog.com/weiym/archive/2012/09/19/191301.html" style="color: #4371a6; cursor: pointer;">理解程序内存</a></span><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">。</span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;"><br /></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">理论上说COM对象如果是以C++接口的方式实现， 虚表会位于PE文件的只读数据节(.rdata), 并且所有该类型的对象都共享该虚表， 所以我们只要创建一个该类型对象，我们就可以获得其他人创建的该类型对象的虚表位置，我们就可以改写该虚表实现Hook（实际操作时需要通过VirtualProtect修改页面的只读属性才能写入）。</span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;"><br /></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">但是实际上COM的虚表只是一块内存， 它并不一定是以C++实现， 所以它可以存在于任何内存的任何地方。另外对象的虚表也不一定是所有同类型的对象共享同一虚表， 我们完全可以每个对象都有自己的一份虚表。比如我发现</span><span style="line-height: 20px;">IDirect3D9是大家共享同一虚表的（存在D3D9.dll）， 但是IDirect3DDevice9就是每个对象都有自己的虚表了(存在于堆heap)。所以如果你要Hook</span><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">&nbsp;IDirect3DDevice9接口，通过修改虚表实际上没法实现。</span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;"><br /></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">但是尽管有时每个对象的虚表不一样，同类型对象虚表里的函数地址却都是一样的， 所以这种情况下我们可以通过inline Hook直接修改函数代码。当然有些情况下如果是静态链接库，即使函数代码也是每个模块都有自己的一份， 这种情况下就只能反汇编获取虚表和函数的地址了。</span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;"><br /></span></div><div style="font-family: 微软雅黑; line-height: normal; orphans: 2; widows: 2; background-color: #ffffff;"><span style="line-height: 20px;">最后，总结一下， 上面主要探讨了Windows上的各种Hook技术，通过将这些Hook技术组起来， 可以实现很多意想不到的功能， 比如我们完全可以通过Hook D3D实现Win7任务栏那种Thumbnail预览的效果</span>(当然该效果可以直接由DWM API实现, 但是如果我们可以通过HOOK以动画的方式实现是不是更有趣 )<span style="line-height: 20px; font-family: 'Microsoft Yahei'; color: #2a2a2a;">。<br /><br />本文转自：</span><a href="http://www.cppblog.com/weiym/archive/2013/10/30/203991.html">http://www.cppblog.com/weiym/archive/2013/10/30/203991.html</a></div><img src ="http://www.cppblog.com/wanghaiguang/aggbug/204158.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2013-11-08 08:15 <a href="http://www.cppblog.com/wanghaiguang/archive/2013/11/08/204158.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++ 查看代码执行的时间</title><link>http://www.cppblog.com/wanghaiguang/archive/2013/10/22/203862.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Tue, 22 Oct 2013 00:20:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2013/10/22/203862.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/203862.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2013/10/22/203862.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/203862.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/203862.html</trackback:ping><description><![CDATA[示例代码：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #0000FF; ">long</span>&nbsp;begin,end;<br /><span style="color: #0000FF; ">double</span>&nbsp;time;<br />begin&nbsp;=&nbsp;clock();<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">查看代码</span><span style="color: #008000; "><br /></span>}<br />end&nbsp;&nbsp;=&nbsp;clock();<br />time&nbsp;=&nbsp;(<span style="color: #0000FF; ">double</span>)(end&nbsp;-&nbsp;begin)&nbsp;/&nbsp;CLOCKS_PER_SEC;<br />Logger-&gt;Info(&nbsp;"%f&nbsp;seconds\n",&nbsp;time&nbsp;);</div><br />其他参考：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#include&lt;iostream&gt;&nbsp;<br />include&lt;windows.h&gt;&nbsp;<br /><span style="color: #0000FF; ">using</span>&nbsp;<span style="color: #0000FF; ">namespace</span>&nbsp;std;<br /><span style="color: #0000FF; ">int</span>&nbsp;main()&nbsp;<br />{&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;start_time=GetTickCount();&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">此处为被测试代码</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;end_time=GetTickCount();&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;"The&nbsp;run&nbsp;time&nbsp;is:"&lt;&lt;(end_time-start_time)&lt;&lt;"ms!"&lt;&lt;endl;<span style="color: #008000; ">//</span><span style="color: #008000; ">输出运行时间</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;&nbsp;<br />} &nbsp;</div><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="font-family: Verdana;">#include&lt;</span><span style="font-family: Verdana;">iostream</span><span style="font-family: Verdana;">&gt;</span>&nbsp;<br /><span style="font-family: Verdana;">#include</span><span style="font-family: Verdana;">&lt;</span><span style="font-family: Verdana;">time.h</span><span style="font-family: Verdana;">&gt;</span>&nbsp;<br /><span style="color: #0000ff; font-family: Verdana;">using</span>&nbsp;<span style="color: #0000ff; font-family: Verdana;">namespace</span><span style="font-family: Verdana;">&nbsp;std;</span><br /><span style="color: #0000ff; font-family: Verdana;">int</span><span style="font-family: Verdana;">&nbsp;main()</span><br /><span style="font-family: Verdana;">{&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;clock_t&nbsp;start_time</span><span style="font-family: Verdana;">=</span><span style="font-family: Verdana;">clock();&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;{&nbsp;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">被测试代码&nbsp;</span><span style="color: #008000; "><br /></span><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;clock_t&nbsp;end_time</span><span style="font-family: Verdana;">=</span><span style="font-family: Verdana;">clock();</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;cout</span><span style="font-family: Verdana;">&lt;&lt;</span>&nbsp;<span style="font-family: Verdana;">"</span><span style="font-family: Verdana;">Running&nbsp;time&nbsp;is:&nbsp;</span><span style="font-family: Verdana;">"</span><span style="font-family: Verdana;">&lt;&lt;</span><span style="font-family: Verdana;">static_cast</span><span style="font-family: Verdana;">&lt;</span><span style="color: #0000ff; font-family: Verdana;">double</span><span style="font-family: Verdana;">&gt;</span><span style="font-family: Verdana;">(end_time</span><span style="font-family: Verdana;">-</span><span style="font-family: Verdana;">&nbsp;start_time)</span><span style="font-family: Verdana;">/</span><span style="font-family: Verdana;">CLOCKS_PER_SEC</span><span style="font-family: Verdana;">*</span><span style="font-family: Verdana;">1000</span><span style="font-family: Verdana;">&lt;&lt;</span><span style="font-family: Verdana;">"</span><span style="font-family: Verdana;">ms</span><span style="font-family: Verdana;">"</span><span style="font-family: Verdana;">&lt;&lt;</span><span style="font-family: Verdana;">endl;</span><span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">输出运行时间&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">return</span>&nbsp;<span style="font-family: Verdana;">0</span><span style="font-family: Verdana;">;&nbsp;</span><br /><span style="font-family: Verdana;">}&nbsp;</span></div><img src ="http://www.cppblog.com/wanghaiguang/aggbug/203862.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2013-10-22 08:20 <a href="http://www.cppblog.com/wanghaiguang/archive/2013/10/22/203862.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++ 使用 gsoap 调用 java WebService 中文乱码</title><link>http://www.cppblog.com/wanghaiguang/archive/2013/08/29/202856.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Thu, 29 Aug 2013 11:57:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2013/08/29/202856.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/202856.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2013/08/29/202856.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/202856.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/202856.html</trackback:ping><description><![CDATA[<span style="font-family: Verdana; font-size: 12pt;">问题产生：</span><br />&nbsp; &nbsp; &nbsp; &nbsp;<span style="font-family: Verdana; font-size: 12pt;">使用</span><span style="font-family: Verdana; font-size: 12pt;">gsoap</span><span style="font-family: Verdana; font-size: 12pt;">时，如果</span><span style="font-family: Verdana; font-size: 12pt;">WebService</span><span style="font-family: Verdana; font-size: 12pt;">服务端及客户调用端都使用</span><span style="font-family: Verdana; font-size: 12pt;"> C++ </span><span style="font-family: Verdana; font-size: 12pt;">，</span> <span style="font-family: Verdana; font-size: 12pt;">再传递中文时不会存在乱码问题，</span>  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: Verdana; font-size: 12pt;">当客户端为</span><span style="font-family: Verdana; font-size: 12pt;"> C++ </span><span style="font-family: Verdana; font-size: 12pt;">，</span><span style="font-family: Verdana; font-size: 12pt;">WebService</span><span style="font-family: Verdana; font-size: 12pt;">服务端使用</span><span style="font-family: Verdana; font-size: 12pt;">Java</span><span style="font-family: Verdana; font-size: 12pt;">、</span><span style="font-family: Verdana; font-size: 12pt;">domino</span><span style="font-family: Verdana; font-size: 12pt;">，传递中文则会有乱码问题。</span></p>  <p><span style="font-family: Verdana; font-size: 12pt;">产生原因：</span></p>  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: Verdana; font-size: 12pt;">宽字符的原因<br /><br /></span><p class="MsoNormal"><span style="font-family:宋体;mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font:
minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin"></span></p><div><p><span style="font-family: Verdana; font-size: 12pt;">解决办法</span><span style="font-family: Verdana; font-size: 12pt;">(</span><span style="font-family: Verdana; font-size: 12pt;">一</span><span style="font-family: Verdana; font-size: 12pt;">)</span><span style="font-family: Verdana; font-size: 12pt;">：</span></p>  <p>&nbsp;&nbsp;&nbsp; <span style="font-family: Verdana; font-size: 12pt;">在程序中首先设置本地代码页</span></p>  <p><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp; vista </span><span style="font-family: Verdana; font-size: 12pt;">操作系统：</span>&nbsp;</p>  <p><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-family: Verdana; font-size: 12pt; color: red;"> setlocal(LC_ALL,"Chinese");</span></p>  <p><span style="font-family: Verdana; font-size: 12pt; color: red;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; soap_set_mode(soap,SOAP_C_MBSTRING);</span></p>  <p><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp; windowsxp </span><span style="font-family: Verdana; font-size: 12pt;">操作系统：</span></p>  <p><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-family: Verdana; font-size: 12pt; color: red;"> setlocal(LC_ALL,"chs");</span></p>  <p><span style="font-family: Verdana; font-size: 12pt; color: red;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; soap_set_mode(soap,SOAP_C_MBSTRING);</span></p>    <p>&nbsp;</p>  <p><span style="font-family: Verdana; font-size: 12pt;">解决方法（二）</span></p>  <p><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp; 1. </span><span style="font-family: Verdana; font-size: 12pt;">使用</span><span style="font-family: Verdana; font-size: 12pt;"> wsdl2h.exe </span><span style="font-family: Verdana; font-size: 12pt;">通过</span><span style="font-family: Verdana; font-size: 12pt;">wsdl</span><span style="font-family: Verdana; font-size: 12pt;">描述文件创建</span><span style="font-family: Verdana; font-size: 12pt;">C++</span><span style="font-family: Verdana; font-size: 12pt;">头文件（</span><span style="font-family: Verdana; font-size: 12pt;">test.h</span><span style="font-family: Verdana; font-size: 12pt;">）；</span></p>  <p><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp; 2. </span><span style="font-family: Verdana; font-size: 12pt;">将头文件</span><span style="font-family: Verdana; font-size: 12pt;">(test.h)</span><span style="font-family: Verdana; font-size: 12pt;">中</span><span style="font-family: Verdana; font-size: 12pt;"> std:string* </span><span style="font-family: Verdana; font-size: 12pt;">使用</span><span style="font-family: Verdana; font-size: 12pt;">wchar_t* </span><span style="font-family: Verdana; font-size: 12pt;">替换；</span></p>  <p><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp; 3. </span><span style="font-family: Verdana; font-size: 12pt;">使用</span><span style="font-family: Verdana; font-size: 12pt;"> soapcpp2.exe -i test.h ,</span><span style="font-family: Verdana; font-size: 12pt;">生成相关的</span><span style="font-family: Verdana; font-size: 12pt;">cpp</span><span style="font-family: Verdana; font-size: 12pt;">及</span><span style="font-family: Verdana; font-size: 12pt;">h</span><span style="font-family: Verdana; font-size: 12pt;">文件</span></p>  <p><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp; 4. </span><span style="font-family: Verdana; font-size: 12pt;">使用</span><span style="font-family: Verdana; font-size: 12pt;"> C++ </span><span style="font-family: Verdana; font-size: 12pt;">时，需要将接收的</span><span style="font-family: Verdana; font-size: 12pt;">wchar_t</span><span style="font-family: Verdana; font-size: 12pt;">类型数据转换为</span><span style="font-family: Verdana; font-size: 12pt;">char</span><span style="font-family: Verdana; font-size: 12pt;">，</span> <span style="font-family: Verdana; font-size: 12pt;">使用</span><span style="font-family: Verdana; font-size: 12pt;">WideCharToMultiByte</span><span style="font-family: Verdana; font-size: 12pt;">函数</span>&nbsp;&nbsp;&nbsp; </p>  <p><span style="font-family: Verdana; font-size: 12pt;">后续：</span></p>  <p><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp; soap</span><span style="font-family: Verdana; font-size: 12pt;">在对字符编码转换时，调用</span><span style="font-family: Verdana; font-size: 12pt;"> wctomb </span><span style="font-family: Verdana; font-size: 12pt;">函数，该函数的调用在</span><span style="font-family: Verdana; font-size: 12pt;"> stdcoap2.cpp </span><span style="font-family: Verdana; font-size: 12pt;">文件中，代码调试跟踪至此，查看</span> <span style="font-family: Verdana; font-size: 12pt;">该函数的返回值是否正确，</span><span style="font-family: Verdana; font-size: 12pt;">-1</span><span style="font-family: Verdana; font-size: 12pt;">表示字符集设置不正确。<br /><br /></span><span style="font-family: Verdana; font-size: 12pt;">本文转自：</span><a href="http://wenhaidongke.blog.163.com/blog/static/128070090200982313655668/"><span style="font-family: Verdana; font-size: 12pt;">http://wenhaidongke.blog.163.com/blog/static/128070090200982313655668/</span></a></p></div><p class="MsoNormal"><span lang="EN-US"></span></p></p><img src ="http://www.cppblog.com/wanghaiguang/aggbug/202856.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2013-08-29 19:57 <a href="http://www.cppblog.com/wanghaiguang/archive/2013/08/29/202856.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tcp连接探测Keepalive和心跳包（转载）</title><link>http://www.cppblog.com/wanghaiguang/archive/2013/08/14/202537.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Wed, 14 Aug 2013 11:14:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2013/08/14/202537.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/202537.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2013/08/14/202537.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/202537.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/202537.html</trackback:ping><description><![CDATA[<span style="color: #333333; font-family: verdana, sans-serif; font-size: 12pt; line-height: 19px; background-color: #ffffff;"><p><span style="font-size: 13px;">&nbsp; &nbsp; &nbsp;&nbsp;</span><span style="font-size: 12pt;"> 采用TCP连接的C/S模式软件，连接的双方在连接空闲状态时，如果任意一方意外崩溃、当机、网线断开或路由器故障，另一方无法得知TCP连接已经失效，除非继续在此连接上发送数据导致错误返回。很多时候，这不是我们需要的。我们希望服务器端和客户端都能及时有效地检测到连接失效，然后优雅地完成一些清理工作并把错误报告给用户。</span><br style="font-size: 13px;" /><span style="font-size: 13px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 12pt;">如何及时有效地检测到一方的非正常断开，一直有两种技术可以运用。一种是由TCP协议层实现的Keepalive，另一种是由应用层自己实现的心跳包</span><span style="font-size: 12pt;">。</span><br style="font-size: 13px;" /><span style="font-size: 13px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 12pt;">TCP默认并不开启Keepalive功能，因为开启Keepalive功能需要消耗额外的宽带和流量，尽管这微不足道，但在按流量计费的环境下增加了费用，另一方面，Keepalive设置不合理时可能会因为短暂的网络波动而断开健康的TCP连接。并且，默认的Keepalive超时需要7,200,000 milliseconds，即2小时，探测次数为5次。</span><br style="font-size: 13px;" /><span style="font-size: 13px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 12pt;">对于Win2K/XP/2003，可以从下面的注册表项找到影响整个系统所有连接的keepalive参数：</span><br style="font-size: 13px;" /><span style="font-size: 13px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 12pt;">[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Tcpip/Parameters]</span><br style="font-size: 13px;" /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "</span><span style="font-size: 12pt;">KeepAliveTime&#8221;=dword:006ddd00</span><br style="font-size: 13px;" /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"</span><span style="font-size: 12pt;">KeepAliveInterval"=dword:000003e8</span>&nbsp;<br style="font-size: 13px;" /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "</span><span style="font-size: 12pt;">MaxDataRetries"="5"<br /><br /></span><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;对于实用的程序来说，2小时的空闲时间太长。因此，我们需要手工开启Keepalive功能并设置合理的Keepalive参数。</span></p><div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; width: 1144.625px; word-break: break-all;"><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" /><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;开启KeepAlive</span><span style="color: #008000;"><br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #000000;">BOOL&nbsp;bKeepAlive&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;TRUE;<br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;nRet&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;::setsockopt(socket_handle,&nbsp;SOL_SOCKET,&nbsp;SO_KEEPALIVE,&nbsp;(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">*</span><span style="color: #000000;">)</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">bKeepAlive,&nbsp;</span><span style="color: #0000ff;">sizeof</span><span style="color: #000000;">(bKeepAlive));<br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" /><br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(nRet&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;SOCKET_ERROR)<br /><img id="Codehighlighter1_172_188_Open_Image" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" alt="" /></span><span id="Codehighlighter1_172_188_Open_Text"><span style="color: #000000;">{<br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" /></span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;FALSE;<br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" />}</span></span><span style="color: #000000;"><br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" /><br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;设置KeepAlive参数</span><span style="color: #008000;"><br /><img id="Codehighlighter1_233_235_Open_Image" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" alt="" /></span><span style="color: #000000;">tcp_keepalive&nbsp;alive_in&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span id="Codehighlighter1_233_235_Open_Text"><span style="color: #000000;">{</span><span style="color: #000000;">0</span><span style="color: #000000;">}</span></span><span style="color: #000000;">;<br /><img id="Codehighlighter1_264_266_Open_Image" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" alt="" />tcp_keepalive&nbsp;alive_out&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span id="Codehighlighter1_264_266_Open_Text"><span style="color: #000000;">{</span><span style="color: #000000;">0</span><span style="color: #000000;">}</span></span><span style="color: #000000;">;<br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" />alive_in.keepalivetime&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">5000</span><span style="color: #000000;">;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;开始首次KeepAlive探测前的TCP空闭时间</span><span style="color: #008000;"><br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #000000;"><br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" />alive_in.keepaliveinterval&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">1000</span><span style="color: #000000;">;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;两次KeepAlive探测间的时间间隔</span><span style="color: #008000;"><br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #000000;"><br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" />alive_in.onoff&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;TRUE;<br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" />unsigned&nbsp;</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;ulBytesReturn&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">0</span><span style="color: #000000;">;<br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" /><br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" />nRet&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;WSAIoctl(socket_handle,&nbsp;SIO_KEEPALIVE_VALS,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">alive_in,&nbsp;</span><span style="color: #0000ff;">sizeof</span><span style="color: #000000;">(alive_in),<br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #000000;">&amp;</span><span style="color: #000000;">alive_out,&nbsp;</span><span style="color: #0000ff;">sizeof</span><span style="color: #000000;">(alive_out),&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">ulBytesReturn,&nbsp;NULL,&nbsp;NULL);<br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(nRet&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;SOCKET_ERROR)<br /><img id="Codehighlighter1_611_629_Open_Image" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" alt="" /></span><span id="Codehighlighter1_611_629_Open_Text"><span style="color: #000000;">{<br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" /></span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;FALSE;<br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" /><br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" /><br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" />}</span></span><span style="color: #000000;"><br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" /><br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" /></span></div><br /><p>开启Keepalive选项之后，对于使用IOCP模型的服务器端程序来说，一旦检测到连接断开，GetQueuedCompletionStatus函数将立即返回FALSE，使得服务器端能及时清除该连接、释放该连接相关的资源。对于使用select模型的客户端来说，连接断开被探测到时，以recv目的阻塞在socket上的select方法将立即返回SOCKET_ERROR，从而得知连接已失效，客户端程序便有机会及时执行清除工作、提醒用户或重新连接。<br /></p><p>&nbsp;</p><p>另一种技术，由应用程序自己发送心跳包来检测连接的健康性。客户端可以在一个Timer中或低级别的线程中定时向发服务器发送一个短小精悍的包，并等待服务器的回应。客户端程序在一定时间内没有收到服务器回应即认为连接不可用，同样，服务器在一定时间内没有收到客户端的心跳包则认为客户端已经掉线。<br /><br /></p><p>&nbsp;</p><p>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++</p><p>　windows下此处的&#8221;非正常断开&#8221;指TCP连接不是以优雅的方式断开,如网线故障等物理链路的原因,还有突然主机断电等原因.</p><p>有两种方法可以检测:</p><p>1.TCP连接双方定时发握手消息</p><p>&nbsp;</p><p><br />2.利用TCP协议栈中的KeepAlive探测<br />第二种方法简单可靠,只需对TCP连接两个Socket设定KeepAlive探测,<br />所以本文只讲第二种方法在Linux,Window2000下的实现(在其它的平台上没有作进一步的测试)</p><div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; width: 1144.625px; word-break: break-all;"><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" /><span style="color: #000000;"><br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" />Windows&nbsp;2000平台下&nbsp;头文件<br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" />#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">mstcpip.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #008000;">//</span><span style="color: #008000;">定义结构及宏<br />/*</span><span style="color: #008000;"><br /><img id="Codehighlighter1_72_133_Open_Image" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" alt="" /></span><span style="color: #0000ff;">struct</span><span style="color: #000000;">&nbsp;TCP_KEEPALIVE&nbsp;</span><span id="Codehighlighter1_72_133_Open_Text"><span style="color: #000000;">{<br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" />u_longonoff;<br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" />u_longkeepalivetime;<br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" />u_longkeepaliveinterval;<br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" />}</span></span><span style="color: #000000;">&nbsp;;<br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" />*/<br /><img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" /><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp; tcp_keepalive live,liveout;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;live.keepaliveinterval=5000; //每5秒发一次探测报文,发5次没有回应，就断开<br />&nbsp;&nbsp;&nbsp;&nbsp;live.keepalivetime=30000;//超过30s没有数据，就发送控测包<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;live.onoff=TRUE;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;int Opt = 1;<br />&nbsp;&nbsp;&nbsp;&nbsp;int iRet = setsockopt(Accept,SOL_SOCKET,SO_KEEPALIVE,(char *)&amp;Opt,sizeof(int));&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;if(iRet == 0)<br /></span>&nbsp; &nbsp;&nbsp;<span style="color: #000000;">{<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DWORD dw;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if(::WSAIoctl(Accept,SIO_KEEPALIVE_VALS,<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;live,sizeof(live),&amp;liveout,sizeof(liveout),<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;dw,NULL,NULL)== SOCKET_ERROR){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br />}<img alt="" align="top" src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" /><br /><br /></span></div><p><br />ACE下代码 //by rainfish blog.csdn.net/bat603</p><p>&nbsp;</p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff; font-size: 12pt;">int</span><span style="color: #000000; font-size: 12pt;">&nbsp;Opt&nbsp;</span><span style="color: #000000; font-size: 12pt;">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 12pt;">1</span><span style="color: #000000; font-size: 12pt;">;<br /></span><span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">在测试过程中，发现检测的次数是5次，即下面的设置中，从最近一次消息开始计算的10秒后，每次间隔5秒，连续发送5次，即35秒发现网络断了</span><span style="color: #008000; "><br /></span><span style="color: #000000; font-size: 12pt;">tcp_keepalive&nbsp;live,liveout;&nbsp;<br /></span><span style="color: #000000; font-size: 12pt;">live.keepaliveinterval</span><span style="color: #000000; font-size: 12pt;">=</span><span style="color: #000000; font-size: 12pt;">5000</span><span style="color: #000000; font-size: 12pt;">;&nbsp;</span><span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">每次检测的间隔&nbsp;（单位毫秒）</span><span style="color: #008000; "><br /></span><span style="color: #000000; font-size: 12pt;">live.keepalivetime</span><span style="color: #000000; font-size: 12pt;">=</span><span style="color: #000000; font-size: 12pt;">10000</span><span style="color: #000000; font-size: 12pt;">;&nbsp;</span><span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">第一次开始发送的时间（单位毫秒）</span><span style="color: #008000; "><br /></span><span style="color: #000000; font-size: 12pt;">live.onoff</span><span style="color: #000000; font-size: 12pt;">=</span><span style="color: #000000; font-size: 12pt;">TRUE;&nbsp;<br /></span><span style="color: #0000ff; font-size: 12pt;">int</span><span style="color: #000000; font-size: 12pt;">&nbsp;iRet&nbsp;</span><span style="color: #000000; font-size: 12pt;">=</span><span style="color: #000000; font-size: 12pt;">&nbsp;stream.set_option(SOL_SOCKET,SO_KEEPALIVE,</span><span style="color: #000000; font-size: 12pt;">&amp;</span><span style="color: #000000; font-size: 12pt;">Opt,</span><span style="color: #0000ff; font-size: 12pt;">sizeof</span><span style="color: #000000; font-size: 12pt;">(</span><span style="color: #0000ff; font-size: 12pt;">int</span><span style="color: #000000; font-size: 12pt;">));&nbsp;<br /></span><span style="color: #0000ff; font-size: 12pt;">if</span><span style="color: #000000; font-size: 12pt;">(iRet&nbsp;</span><span style="color: #000000; font-size: 12pt;">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 12pt;">0</span><span style="color: #000000; font-size: 12pt;">)<br /></span><span style="color: #000000; font-size: 12pt;">{&nbsp;<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #000000; font-size: 12pt;">DWORD&nbsp;dw;<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">此处显示了在ACE下获取套接字的方法，即句柄的(SOCKET)化就是句柄</span><span style="color: #008000; "><br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-size: 12pt;">if</span><span style="color: #000000; font-size: 12pt;">(WSAIoctl((SOCKET)h,SIO_KEEPALIVE_VALS,</span><span style="color: #000000; font-size: 12pt;">&amp;</span><span style="color: #000000; font-size: 12pt;">live,</span><span style="color: #0000ff; font-size: 12pt;">sizeof</span><span style="color: #000000; font-size: 12pt;">(live),<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #000000; font-size: 12pt;">&amp;</span><span style="color: #000000; font-size: 12pt;">liveout,</span><span style="color: #0000ff; font-size: 12pt;">sizeof</span><span style="color: #000000; font-size: 12pt;">(liveout),</span><span style="color: #000000; font-size: 12pt;">&amp;</span><span style="color: #000000; font-size: 12pt;">dw,NULL,NULL)</span><span style="color: #000000; font-size: 12pt;">==</span><span style="color: #000000; font-size: 12pt;">&nbsp;SOCKET_ERROR)<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #000000; font-size: 12pt;">{<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">Delete&nbsp;Client&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-size: 12pt;">return</span><span style="color: #000000; font-size: 12pt;">;&nbsp;<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #000000; font-size: 12pt;">}&nbsp;<br /></span><span style="color: #000000; font-size: 12pt;">}</span></div><p>&nbsp;</p><p><br /></p><p>Linux平台下</p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; font-size: 12pt;">#include&nbsp;</span><span style="color: #000000; font-size: 12pt;">"</span><span style="color: #000000; font-size: 12pt;">/usr/include/linux/tcp.h</span><span style="color: #000000; font-size: 12pt;">"</span><span style="color: #000000; "><br /></span><span style="color: #000000; font-size: 12pt;">#include&nbsp;</span><span style="color: #000000; font-size: 12pt;">"</span><span style="color: #000000; font-size: 12pt;">/usr/include/linux/socket.h</span><span style="color: #000000; font-size: 12pt;">"</span><span style="color: #000000; "><br /></span><span style="color: #808080; font-size: 12pt;">///</span><span style="color: #008000; font-size: 12pt;">/KeepAlive实现，单位秒</span><span style="color: #808080; "><br /></span><span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">下面代码要求有ACE,如果没有包含ACE,则请把用到的ACE函数改成linux相应的接口</span><span style="color: #008000; "><br /></span><span style="color: #0000ff; font-size: 12pt;">int</span><span style="color: #000000; font-size: 12pt;">&nbsp;keepAlive&nbsp;</span><span style="color: #000000; font-size: 12pt;">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 12pt;">1</span><span style="color: #000000; font-size: 12pt;">;</span><span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">设定KeepAlive</span><span style="color: #008000; "><br /></span><span style="color: #0000ff; font-size: 12pt;">int</span><span style="color: #000000; font-size: 12pt;">&nbsp;keepIdle&nbsp;</span><span style="color: #000000; font-size: 12pt;">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 12pt;">5</span><span style="color: #000000; font-size: 12pt;">;</span><span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">开始首次KeepAlive探测前的TCP空闭时间</span><span style="color: #008000; "><br /></span><span style="color: #0000ff; font-size: 12pt;">int</span><span style="color: #000000; font-size: 12pt;">&nbsp;keepInterval&nbsp;</span><span style="color: #000000; font-size: 12pt;">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 12pt;">5</span><span style="color: #000000; font-size: 12pt;">;</span><span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">两次KeepAlive探测间的时间间隔</span><span style="color: #008000; "><br /></span><span style="color: #0000ff; font-size: 12pt;">int</span><span style="color: #000000; font-size: 12pt;">&nbsp;keepCount&nbsp;</span><span style="color: #000000; font-size: 12pt;">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 12pt;">3</span><span style="color: #000000; font-size: 12pt;">;</span><span style="color: #008000; font-size: 12pt;">//</span><span style="color: #008000; font-size: 12pt;">判定断开前的KeepAlive探测次数</span><span style="color: #008000; "><br /></span><span style="color: #0000ff; font-size: 12pt;">if</span><span style="color: #000000; font-size: 12pt;">(setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(</span><span style="color: #0000ff; font-size: 12pt;">void</span><span style="color: #000000; font-size: 12pt;">*</span><span style="color: #000000; font-size: 12pt;">)</span><span style="color: #000000; font-size: 12pt;">&amp;</span><span style="color: #000000; font-size: 12pt;">keepAlive,</span><span style="color: #0000ff; font-size: 12pt;">sizeof</span><span style="color: #000000; font-size: 12pt;">(keepAlive))&nbsp;</span><span style="color: #000000; font-size: 12pt;">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 12pt;">-</span><span style="color: #000000; font-size: 12pt;">1</span><span style="color: #000000; font-size: 12pt;">)<br /></span><span style="color: #000000; font-size: 12pt;">{<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #000000; font-size: 12pt;">ACE_DEBUG&nbsp;((LM_INFO,<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #000000; font-size: 12pt;">ACE_TEXT&nbsp;(</span><span style="color: #000000; font-size: 12pt;">"</span><span style="color: #000000; font-size: 12pt;">(%P|%t)&nbsp;setsockopt&nbsp;SO_KEEPALIVE&nbsp;error!/n</span><span style="color: #000000; font-size: 12pt;">"</span><span style="color: #000000; font-size: 12pt;">)));<br /></span><span style="color: #000000; font-size: 12pt;">}<br /></span><span style="color: #0000ff; font-size: 12pt;">if</span><span style="color: #000000; font-size: 12pt;">(setsockopt(s,SOL_TCP,TCP_KEEPIDLE,(</span><span style="color: #0000ff; font-size: 12pt;">void</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 12pt;">*</span><span style="color: #000000; font-size: 12pt;">)</span><span style="color: #000000; font-size: 12pt;">&amp;</span><span style="color: #000000; font-size: 12pt;">keepIdle,</span><span style="color: #0000ff; font-size: 12pt;">sizeof</span><span style="color: #000000; font-size: 12pt;">(keepIdle))&nbsp;</span><span style="color: #000000; font-size: 12pt;">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 12pt;">-</span><span style="color: #000000; font-size: 12pt;">1</span><span style="color: #000000; font-size: 12pt;">)<br /></span><span style="color: #000000; font-size: 12pt;">{<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #000000; font-size: 12pt;">ACE_DEBUG&nbsp;((LM_INFO,<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #000000; font-size: 12pt;">ACE_TEXT&nbsp;(</span><span style="color: #000000; font-size: 12pt;">"</span><span style="color: #000000; font-size: 12pt;">(%P|%t)&nbsp;setsockopt&nbsp;TCP_KEEPIDLE&nbsp;error!/n</span><span style="color: #000000; font-size: 12pt;">"</span><span style="color: #000000; font-size: 12pt;">)));<br /></span><span style="color: #000000; font-size: 12pt;">}<br /></span><span style="color: #0000ff; font-size: 12pt;">if</span><span style="color: #000000; font-size: 12pt;">(setsockopt(s,SOL_TCP,TCP_KEEPINTVL,(</span><span style="color: #0000ff; font-size: 12pt;">void</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 12pt;">*</span><span style="color: #000000; font-size: 12pt;">)</span><span style="color: #000000; font-size: 12pt;">&amp;</span><span style="color: #000000; font-size: 12pt;">keepInterval,</span><span style="color: #0000ff; font-size: 12pt;">sizeof</span><span style="color: #000000; font-size: 12pt;">(keepInterval))&nbsp;</span><span style="color: #000000; font-size: 12pt;">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 12pt;">-</span><span style="color: #000000; font-size: 12pt;">1</span><span style="color: #000000; font-size: 12pt;">)<br /></span><span style="color: #000000; font-size: 12pt;">{<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #000000; font-size: 12pt;">ACE_DEBUG&nbsp;((LM_INFO,<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #000000; font-size: 12pt;">ACE_TEXT&nbsp;(</span><span style="color: #000000; font-size: 12pt;">"</span><span style="color: #000000; font-size: 12pt;">(%P|%t)&nbsp;setsockopt&nbsp;TCP_KEEPINTVL&nbsp;error!/n</span><span style="color: #000000; font-size: 12pt;">"</span><span style="color: #000000; font-size: 12pt;">)));<br /></span><span style="color: #000000; font-size: 12pt;">}<br /></span><span style="color: #0000ff; font-size: 12pt;">if</span><span style="color: #000000; font-size: 12pt;">(setsockopt(s,SOL_TCP,TCP_KEEPCNT,(</span><span style="color: #0000ff; font-size: 12pt;">void</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 12pt;">*</span><span style="color: #000000; font-size: 12pt;">)</span><span style="color: #000000; font-size: 12pt;">&amp;</span><span style="color: #000000; font-size: 12pt;">keepCount,</span><span style="color: #0000ff; font-size: 12pt;">sizeof</span><span style="color: #000000; font-size: 12pt;">(keepCount))&nbsp;</span><span style="color: #000000; font-size: 12pt;">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 12pt;">-</span><span style="color: #000000; font-size: 12pt;">1</span><span style="color: #000000; font-size: 12pt;">)<br /></span><span style="color: #000000; font-size: 12pt;">{<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #000000; font-size: 12pt;">ACE_DEBUG&nbsp;((LM_INFO,<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #000000; font-size: 12pt;">ACE_TEXT&nbsp;(</span><span style="color: #000000; font-size: 12pt;">"</span><span style="color: #000000; font-size: 12pt;">(%P|%t)setsockopt&nbsp;TCP_KEEPCNT&nbsp;error!/n</span><span style="color: #000000; font-size: 12pt;">"</span><span style="color: #000000; font-size: 12pt;">)));<br /></span><span style="color: #000000; font-size: 12pt;">}</span></div><p>&nbsp;</p><p>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++</p></span><br />本文转自：<a href="http://www.cppblog.com/API/archive/2013/08/13/202516.html" style="font-family: verdana, 'courier new'; font-size: 14px; line-height: 21px;">http://www.cppblog.com/API/archive/2013/08/13/202516.html</a><p>&nbsp;</p><img src ="http://www.cppblog.com/wanghaiguang/aggbug/202537.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2013-08-14 19:14 <a href="http://www.cppblog.com/wanghaiguang/archive/2013/08/14/202537.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++获取屏幕大小</title><link>http://www.cppblog.com/wanghaiguang/archive/2013/08/13/202520.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Tue, 13 Aug 2013 06:09:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2013/08/13/202520.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/202520.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2013/08/13/202520.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/202520.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/202520.html</trackback:ping><description><![CDATA[<strong style="font-size: 12pt;">API:</strong><br style="font-size: 12pt;" /><div style="margin: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: normal; background-color: #ffffff; font-size: 12pt;">要取得屏幕大小，可以用下面几个函数：</div><div style="margin: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: normal; background-color: #ffffff; font-size: 12pt;"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">int</span>&nbsp; cx &nbsp;&nbsp;=&nbsp;&nbsp;<span style="color: #ff00ff;">GetSystemMetrics</span>(&nbsp;<span style="color: #ff00ff;">SM_CXFULLSCREEN&nbsp;</span>);<br /><span style="color: #0000FF; ">int</span>&nbsp; cy &nbsp;&nbsp;=&nbsp;&nbsp;<span style="color: #ff00ff;">GetSystemMetrics</span>(&nbsp;<span style="color: #ff00ff;">SM_CYFULLSCREEN&nbsp;</span>);</div></div><div style="margin: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: normal; background-color: #ffffff; font-size: 12pt;">通过上边两个函数获取的是&nbsp;<strong style="padding: 0px; margin: 0px;">显示屏幕的大小，但不包括任务栏等区域</strong>。<br /><br /></div><div style="margin: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: normal; background-color: #ffffff; font-size: 12pt;"></div><div style="margin: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: normal; background-color: #ffffff; font-size: 12pt;"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">int</span>&nbsp; cx&nbsp;&nbsp;&nbsp;=&nbsp; &nbsp;<span style="color: #ff00ff;">GetSystemMetrics</span>(&nbsp;&nbsp;&nbsp;<span style="color: #ff00ff;">SM_CXSCREEN&nbsp;&nbsp;&nbsp;</span>);&nbsp;&nbsp;&nbsp;<br /><span style="color: #0000FF; ">int</span>&nbsp; cy&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;<span style="color: #ff00ff;">GetSystemMetrics</span>(&nbsp;&nbsp;&nbsp;<span style="color: #ff00ff;">SM_CYSCREEN&nbsp;&nbsp;&nbsp;</span>);</div></div><div style="margin: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: normal; background-color: #ffffff; font-size: 12pt;"></div><div style="margin: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: normal; background-color: #ffffff; font-size: 12pt;"><strong style="padding: 0px; margin: 0px;">这两个函数获取的是真正屏幕的大小。<br /><br />MFC:</strong></div><div style="background-color: #eeeeee; font-size: 12pt; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff;">HDC&nbsp;</span>hDC = &nbsp;::<span style="color: #ff0000;">GetDC</span>(<span style="color: #0000ff;">HWND(</span><span style="color: #ff00ff;">NULL</span>)); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;得到屏幕DC&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">int</span>&nbsp;x &nbsp;= &nbsp;::<span style="color: #ff0000;">GetDeviceCaps</span>(hDC,<span style="color: #ff00ff;">HORZRES</span>); &nbsp; &nbsp; &nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;宽&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">int</span>&nbsp;y &nbsp;= &nbsp;::<span style="color: #ff0000;">GetDeviceCaps</span>(hDC,<span style="color: #ff00ff;">VERTRES</span>); &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;高&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span>::<span style="color: #ff0000;">ReleaseDC</span>(<span style="color: #0000ff;">HWND(</span><span style="color: #ff00ff;">NULL</span>),hDC); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;释放DC</span></div><img src ="http://www.cppblog.com/wanghaiguang/aggbug/202520.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2013-08-13 14:09 <a href="http://www.cppblog.com/wanghaiguang/archive/2013/08/13/202520.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ListControl控件绘制网格线</title><link>http://www.cppblog.com/wanghaiguang/archive/2013/07/12/201722.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Fri, 12 Jul 2013 03:10:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2013/07/12/201722.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/201722.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2013/07/12/201722.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/201722.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/201722.html</trackback:ping><description><![CDATA[<span style="color: #333333; font-family: Verdana; line-height: 24px; background-color: #f5f5f5; font-size: 12pt;">重载&nbsp;DrawItem&nbsp;函数或Onpaint函数</span><span style="color: #333333; font-family: Verdana; line-height: 24px; background-color: #f5f5f5;"><br /></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff; font-family: Verdana;">void</span><span style="font-family: Verdana;">&nbsp;CListCtrlCl::DrawItem(LPDRAWITEMSTRUCT&nbsp;lpDrawItemStruct)</span><br /><span style="font-family: Verdana;">{</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;重绘网格线&nbsp;[7/12/2013&nbsp;dell]</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">const</span><span style="font-family: Verdana;">&nbsp;MSG&nbsp;*msg&nbsp;=&nbsp;GetCurrentMessage();</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;DefWindowProc(&nbsp;msg-&gt;message,&nbsp;msg-&gt;wParam,&nbsp;msg-&gt;lParam&nbsp;);</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;Draw&nbsp;the&nbsp;lines&nbsp;only&nbsp;for&nbsp;LVS_REPORT&nbsp;mode</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">if</span><span style="font-family: Verdana;">(&nbsp;(GetStyle()&nbsp;&amp;&nbsp;LVS_TYPEMASK)&nbsp;==&nbsp;LVS_REPORT&nbsp;)</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;{</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;Get&nbsp;the&nbsp;number&nbsp;of&nbsp;columns</span><span style="color: #008000; "><br /></span><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CClientDC&nbsp;dc(</span><span style="color: #0000ff; font-family: Verdana;">this</span><span style="font-family: Verdana;">&nbsp;);</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CHeaderCtrl*&nbsp;pHeader&nbsp;=&nbsp;(CHeaderCtrl*)GetDlgItem(0);</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">int</span><span style="font-family: Verdana;">&nbsp;nColumnCount&nbsp;=&nbsp;pHeader-&gt;GetItemCount();</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;The&nbsp;bottom&nbsp;of&nbsp;the&nbsp;header&nbsp;corresponds&nbsp;to&nbsp;the&nbsp;top&nbsp;of&nbsp;the&nbsp;line&nbsp;</span><span style="color: #008000; "><br /></span><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RECT&nbsp;rect,&nbsp;rectCol;</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pHeader-&gt;GetClientRect(&nbsp;&amp;rect&nbsp;);</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">int</span><span style="font-family: Verdana;">&nbsp;top&nbsp;=&nbsp;rect.bottom;</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;Now&nbsp;get&nbsp;the&nbsp;client&nbsp;rect&nbsp;so&nbsp;we&nbsp;know&nbsp;the&nbsp;line&nbsp;length&nbsp;and<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;when&nbsp;to&nbsp;stop</span><span style="color: #008000; "><br /></span><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetClientRect(&nbsp;&amp;rect&nbsp;);</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">if</span><span style="font-family: Verdana;">(&nbsp;!GetItemRect(&nbsp;1,&nbsp;&amp;rectCol,&nbsp;LVIR_BOUNDS&nbsp;))</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">return</span><span style="font-family: Verdana;">;</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">int</span><span style="font-family: Verdana;">&nbsp;height1&nbsp;=&nbsp;rectCol.bottom&nbsp;-&nbsp;rectCol.top;</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;The&nbsp;border&nbsp;of&nbsp;the&nbsp;column&nbsp;is&nbsp;offset&nbsp;by&nbsp;the&nbsp;horz&nbsp;scroll</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">int</span><span style="font-family: Verdana;">&nbsp;borderx&nbsp;=&nbsp;0&nbsp;-&nbsp;GetScrollPos(&nbsp;SB_HORZ&nbsp;);</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">for</span><span style="font-family: Verdana;">(&nbsp;</span><span style="color: #0000ff; font-family: Verdana;">int</span><span style="font-family: Verdana;">&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;nColumnCount;&nbsp;i++&nbsp;)</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;Get&nbsp;the&nbsp;next&nbsp;border</span><span style="color: #008000; "><br /></span><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;borderx&nbsp;+=&nbsp;GetColumnWidth(&nbsp;i&nbsp;);</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;if&nbsp;next&nbsp;border&nbsp;is&nbsp;outside&nbsp;client&nbsp;area,&nbsp;break&nbsp;out</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">if</span><span style="font-family: Verdana;">(&nbsp;borderx&nbsp;&gt;=&nbsp;rect.right&nbsp;)&nbsp;</span><span style="color: #0000ff; font-family: Verdana;">break</span><span style="font-family: Verdana;">;</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;Draw&nbsp;the&nbsp;line.</span><span style="color: #008000; "><br /></span><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dc.MoveTo(&nbsp;borderx-1,&nbsp;top</span><span style="color: #008000; font-family: Verdana;">/*</span><span style="color: #008000; font-family: Verdana;">top</span><span style="color: #008000; font-family: Verdana;">*/</span><span style="font-family: Verdana;">);</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dc.LineTo(&nbsp;borderx-1,&nbsp;(2+lpDrawItemStruct-&gt;itemID)*height1</span><span style="color: #008000; font-family: Verdana;">/*</span><span style="color: #008000; font-family: Verdana;">rect.bottom</span><span style="color: #008000; font-family: Verdana;">*/</span><span style="font-family: Verdana;">&nbsp;);</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;Draw&nbsp;the&nbsp;horizontal&nbsp;grid&nbsp;lines<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; font-family: Verdana;">//</span><span style="color: #008000; font-family: Verdana;">&nbsp;First&nbsp;get&nbsp;the&nbsp;height</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">if</span><span style="font-family: Verdana;">(&nbsp;!GetItemRect(&nbsp;0,&nbsp;&amp;rect,&nbsp;LVIR_BOUNDS&nbsp;))</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">return</span><span style="font-family: Verdana;">;</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">int</span><span style="font-family: Verdana;">&nbsp;height&nbsp;=&nbsp;rect.bottom&nbsp;-&nbsp;rect.top;</span><br /><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetClientRect(&nbsp;&amp;rect&nbsp;);</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">int</span><span style="font-family: Verdana;">&nbsp;width&nbsp;=&nbsp;rect.right;</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; font-family: Verdana;">for</span><span style="font-family: Verdana;">(</span><span style="color: #0000ff; font-family: Verdana;">int</span><span style="font-family: Verdana;">&nbsp;i&nbsp;=&nbsp;1;&nbsp;i&nbsp;&lt;=&nbsp;lpDrawItemStruct-&gt;itemID+1;&nbsp;i++&nbsp;)</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dc.MoveTo(&nbsp;0,&nbsp;top&nbsp;+&nbsp;height*i);</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dc.LineTo(&nbsp;width,&nbsp;top&nbsp;+&nbsp;height*i&nbsp;);</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><br /><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;}</span><br /><span style="font-family: Verdana;">}</span></div><br /><span style="font-family: Verdana;">本文转自：</span><a href="http://www.codeguru.com/cpp/controls/listview/gridlines/article.php/c963/Drawing-horizontal-and-vertical-gridlines.htm"><span style="font-family: Verdana;">http://www.codeguru.com/cpp/controls/listview/gridlines/article.php/c963/Drawing-horizontal-and-vertical-gridlines.htm</span></a><img src ="http://www.cppblog.com/wanghaiguang/aggbug/201722.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2013-07-12 11:10 <a href="http://www.cppblog.com/wanghaiguang/archive/2013/07/12/201722.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++UDP广播</title><link>http://www.cppblog.com/wanghaiguang/archive/2013/06/19/201158.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Wed, 19 Jun 2013 10:00:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2013/06/19/201158.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/201158.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2013/06/19/201158.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/201158.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/201158.html</trackback:ping><description><![CDATA[示例代码：<br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->Sock_UDP::Sock_UDP()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;m_socket&nbsp;=&nbsp;INVALID_SOCKET;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;WSAData&nbsp;ws;&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">每个Winsock程序必须使用WSAStartup载入合适的Winsock动态链接库，如果载入失败，WSAStartup将返回SOCKET_ERROR，这个错误就是WSANOTINITIALISED</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(WSAStartup(MAKEWORD(2,2),&amp;ws)!=0)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LOG("WSAStartup&nbsp;failed!&nbsp;Error:&nbsp;%d",&nbsp;WSAGetLastError());<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br />Sock_UDP::~Sock_UDP()<br />{<br />}</div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">/*</span><span style="color: #008000; ">*****************************************************************<br />*&nbsp;函数介绍：对连接进行初始化<br />*&nbsp;输入参数：&nbsp;strIPAddress：广播的ip地址，strPort:&nbsp;端口号<br />*&nbsp;输出参数：<br />*&nbsp;返回值&nbsp;&nbsp;：<br />******************************************************************</span><span style="color: #008000; ">*/</span><br />BOOL&nbsp;Sock_UDP::InitSocket(<span style="color: #0000FF; ">const</span>&nbsp;CString&nbsp;strIPAddress,<span style="color: #0000FF; ">const</span>&nbsp;CString&nbsp;strPort)<br />{&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">创建套接字,ipv4,报文，udp协议</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;m_socket&nbsp;=&nbsp;socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">创建socket失败</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(INVALID_SOCKET&nbsp;==&nbsp;m_socket)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LOG("failed&nbsp;to&nbsp;create&nbsp;socket");<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">false</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">初始化sock地址</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;InitSockAddress(strIPAddress,strPort);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;绑定</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(bind&nbsp;(m_socket,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: #0000FF; ">struct</span>&nbsp;sockaddr&nbsp;FAR&nbsp;*)&nbsp;&amp;m_sockLocalAddress,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">sizeof</span>&nbsp;(m_sockLocalAddress))&nbsp;==&nbsp;SOCKET_ERROR)&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">报错&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LOG("Binding&nbsp;socket&nbsp;failed!&nbsp;Error:&nbsp;%d"&nbsp;,WSAGetLastError());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;closesocket&nbsp;(m_socket);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">false</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;iOptVal=64;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">1秒<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;设置组播存活时间</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(setsockopt&nbsp;(m_socket,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IPPROTO_IP,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: #0000FF; ">char</span>&nbsp;FAR&nbsp;*)&amp;iOptVal,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">sizeof</span>&nbsp;(<span style="color: #0000FF; ">int</span>))&nbsp;==&nbsp;SOCKET_ERROR)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">报错</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LOG("setsockopt&nbsp;failed!&nbsp;Error:&nbsp;%d"&nbsp;,WSAGetLastError());<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;closesocket&nbsp;(m_socket);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">false</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">true</span>;<br />}<br /><br /><span style="color: #008000; ">/*</span><span style="color: #008000; ">*****************************************************************<br />*&nbsp;函数介绍：关闭socket<br />*&nbsp;输入参数：<br />*&nbsp;输出参数：<br />*&nbsp;返回值&nbsp;&nbsp;：<br />******************************************************************</span><span style="color: #008000; ">*/</span><br /><span style="color: #0000FF; ">void</span>&nbsp;Sock_UDP::CleanSocket()<br />{&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;shutdown(m_socket,0x01);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;closesocket(m_socket);<br />&nbsp;&nbsp;&nbsp;&nbsp;WSACleanup();<br />}<br /><br /><span style="color: #008000; ">/*</span><span style="color: #008000; ">*****************************************************************<br />*&nbsp;函数介绍：初始化IP组播地址和端口<br />*&nbsp;输入参数：strIPAddress：ip地址，strPort:&nbsp;端口号<br />*&nbsp;输出参数：<br />*&nbsp;返回值&nbsp;&nbsp;：<br />******************************************************************</span><span style="color: #008000; ">*/</span><br /><span style="color: #0000FF; ">void</span>&nbsp;Sock_UDP::InitSockAddress(<span style="color: #0000FF; ">const</span>&nbsp;CString&nbsp;strIPAddress,<span style="color: #0000FF; ">const</span>&nbsp;CString&nbsp;strPort)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">本地sock地址设置</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;m_sockLocalAddress.sin_family&nbsp;=&nbsp;AF_INET;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">ipv4地址类型</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;m_sockLocalAddress.sin_addr.S_un.S_addr&nbsp;=&nbsp;htonl(INADDR_ANY);<br />&nbsp;&nbsp;&nbsp;&nbsp;m_sockLocalAddress.sin_port&nbsp;=&nbsp;htons(0);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;memset(m_sockLocalAddress.sin_zero,0,8);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">目的sock地址设置<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">IPv4版本</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;m_sockDesAddress.sin_family&nbsp;=&nbsp;AF_INET;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">端口</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;m_sockDesAddress.sin_port&nbsp;=&nbsp;htons&nbsp;(atol(strPort));&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">地址</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;m_sockDesAddress.sin_addr.s_addr&nbsp;=&nbsp;inet_addr&nbsp;(strIPAddress);<br /><br />}</div><br /><img src ="http://www.cppblog.com/wanghaiguang/aggbug/201158.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2013-06-19 18:00 <a href="http://www.cppblog.com/wanghaiguang/archive/2013/06/19/201158.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>内存泄漏以及常见的解决方法</title><link>http://www.cppblog.com/wanghaiguang/archive/2013/05/02/199909.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Thu, 02 May 2013 10:29:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2013/05/02/199909.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/199909.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2013/05/02/199909.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/199909.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/199909.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 之所以撰写这篇文章是因为前段时间花费了很大的精力在已经成熟的代码上再去处理memory leak问题。写此的目的是希望我们应该养成良好的编码习惯，尽可能的避免这样的问题，因为当你对着一大片的代码再去处理此类的问题，此时无疑增加了解决的成本和难度。准确的说属于补救措施了。1. 什么是内存泄漏（memory leak）？&nbsp;指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非...&nbsp;&nbsp;<a href='http://www.cppblog.com/wanghaiguang/archive/2013/05/02/199909.html'>阅读全文</a><img src ="http://www.cppblog.com/wanghaiguang/aggbug/199909.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2013-05-02 18:29 <a href="http://www.cppblog.com/wanghaiguang/archive/2013/05/02/199909.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>四种进程或线程同步互斥的控制方法</title><link>http://www.cppblog.com/wanghaiguang/archive/2013/04/18/199549.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Thu, 18 Apr 2013 09:06:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2013/04/18/199549.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/199549.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2013/04/18/199549.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/199549.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/199549.html</trackback:ping><description><![CDATA[<p style="font-family: Simsun; line-height: 21.328125px;"><span style="font-family: Verdana; font-size: 12pt;">现在流行的进程线程同步互斥的控制机制，其实是由最原始最基本的4种方法实现的。由这4种方法组合优化就有了.Net和Java下灵活多变的，编程简便的线程进程控制手段。&nbsp;</span><br /><span style="font-family: Verdana; font-size: 12pt;">　　这4种方法具体定义如下 在《操作系统教程》ISBN 7-5053-6193-7 一书中可以找到更加详细的解释&nbsp;</span><br /><span style="font-family: Verdana; font-size: 12pt;">　　1、临界区:通过对多线程的串行化来访问公共资源或一段代码，速度快，适合控制数据访问。&nbsp;</span><br /><span style="font-family: Verdana; font-size: 12pt;">　　2、互斥量:为协调共同对一个共享资源的单独访问而设计的。&nbsp;</span><br /><span style="font-family: Verdana; font-size: 12pt;">　　3、信号量:为控制一个具有有限数量用户资源而设计。&nbsp;</span><br /><span style="font-family: Verdana; font-size: 12pt;">　　4、事 件:用来通知线程有一些事件已发生，从而启动后继任务的开始。&nbsp;</span><br />&nbsp;&nbsp;　　</p><p style="font-family: Simsun; line-height: 21.328125px;"><strong style="font-family: Verdana; font-size: 12pt;">临界区（Critical Section）</strong></p><p style="font-family: Simsun; line-height: 21.328125px;"><br /><span style="font-family: Verdana; font-size: 12pt;">　　保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区，那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起，并一直持续到进入临界区的线程离开。临界区在被释放后，其他线程可以继续抢占，并以此达到用原子方式操作共享资源的目的。&nbsp;</span><br /><span style="font-family: Verdana; font-size: 12pt;">　　临界区包含两个操作原语：&nbsp;</span><br /><span style="font-family: Verdana; font-size: 12pt;">　　EnterCriticalSection（） 进入临界区&nbsp;</span><br /><span style="font-family: Verdana; font-size: 12pt;">　　LeaveCriticalSection（） 离开临界区&nbsp;</span><br /><span style="font-family: Verdana; font-size: 12pt;">　　EnterCriticalSection（）语句执行后代码将进入临界区以后无论发生什么，必须确保与之匹配的LeaveCriticalSection（）都能够被执行到。否则临界区保护的共享资源将永远不会被释放。虽然临界区同步速度很快，但却只能用来同步本进程内的线程，而不可用来同步多个进程中的线程。&nbsp;</span><br /><span style="font-family: Verdana; font-size: 12pt;">　　MFC提供了很多功能完备的类，我用MFC实现了临界区。MFC为临界区提供有一个CCriticalSection类，使用该类进行线程同步处理是非常简单的。只需在线程函数中用CCriticalSection类成员函数Lock（）和UnLock（）标定出被保护代码片段即可。Lock（）后代码用到的资源自动被视为临界区内的资源被保护。UnLock后别的线程才能访问这些资源。&nbsp;</span><br />&nbsp;&nbsp;&nbsp;<br /></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">CriticalSection&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;CCriticalSection&nbsp;global_CriticalSection;&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;共享资源&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;global_Array[256];&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">初始化共享资源&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;InitializeArray()&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;i&lt;256;i++)&nbsp;<br />&nbsp;&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;global_Array[i]=I;&nbsp;<br />&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">写线程&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;UINT&nbsp;Global_ThreadWrite(LPVOID&nbsp;pParam)&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;CEdit&nbsp;*ptr=(CEdit&nbsp;*)pParam;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText("");&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">进入临界区&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;global_CriticalSection.Lock();&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;i&lt;256;i++)&nbsp;<br />&nbsp;&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;global_Array[i]=W;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText(global_Array);&nbsp;<br />&nbsp;&nbsp;&nbsp;Sleep(10);&nbsp;<br />&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">离开临界区&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;global_CriticalSection.Unlock();&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;&nbsp;<br />&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">删除线程&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;UINT&nbsp;Global_ThreadDelete(LPVOID&nbsp;pParam)&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;CEdit&nbsp;*ptr=(CEdit&nbsp;*)pParam;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText("");&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">进入临界区&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;global_CriticalSection.Lock();&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;i&lt;256;i++)&nbsp;<br />&nbsp;&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;global_Array[i]=D;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText(global_Array);&nbsp;<br />&nbsp;&nbsp;&nbsp;Sleep(10);&nbsp;<br />&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">离开临界区&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;global_CriticalSection.Unlock();&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;&nbsp;<br />&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">创建线程并启动线程&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;CCriticalSectionsDlg::OnBnClickedButtonLock()&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">Start&nbsp;the&nbsp;first&nbsp;Thread&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;CWinThread&nbsp;*ptrWrite&nbsp;=&nbsp;AfxBeginThread(Global_ThreadWrite,&nbsp;<br />&nbsp;&nbsp;&nbsp;&amp;m_Write,&nbsp;<br />&nbsp;&nbsp;&nbsp;THREAD_PRIORITY_NORMAL,&nbsp;<br />&nbsp;&nbsp;&nbsp;0,&nbsp;<br />&nbsp;&nbsp;&nbsp;CREATE_SUSPENDED);&nbsp;<br />&nbsp;&nbsp;&nbsp;ptrWrite-&gt;ResumeThread();&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">Start&nbsp;the&nbsp;second&nbsp;Thread&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;CWinThread&nbsp;*ptrDelete&nbsp;=&nbsp;AfxBeginThread(Global_ThreadDelete,&nbsp;<br />&nbsp;&nbsp;&nbsp;&amp;m_Delete,&nbsp;<br />&nbsp;&nbsp;&nbsp;THREAD_PRIORITY_NORMAL,&nbsp;<br />&nbsp;&nbsp;&nbsp;0,&nbsp;<br />&nbsp;&nbsp;&nbsp;CREATE_SUSPENDED);&nbsp;<br />&nbsp;&nbsp;&nbsp;ptrDelete-&gt;ResumeThread();&nbsp;<br />&nbsp;&nbsp;}&nbsp;</div>&nbsp;&nbsp;&nbsp;<br /><span style="font-family: Verdana; font-size: 12pt;">　　在测试程序中，Lock UnLock两个按钮分别实现，在有临界区保护共享资源的执行状态，和没有临界区保护共享资源的执行状态。&nbsp;</span><br />　<p>&nbsp;</p><p style="font-family: Simsun; line-height: 21.328125px;"><strong style="font-family: Verdana; font-size: 12pt;">互斥量（Mutex）</strong><span style="font-family: Verdana; font-size: 12pt;">&nbsp;</span><br style="font-family: Verdana; font-size: 12pt;" /><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;</span><br style="font-family: Verdana; font-size: 12pt;" /><span style="font-family: Verdana; font-size: 12pt;">　　互斥量跟临界区很相似，只有拥有互斥对象的线程才具有访问资源的权限，由于互斥对象只有一个，因此就决定了任何情况下此共享资源都不会同时被多个线程所访问。当前占据资源的线程在任务处理完后应将拥有的互斥对象交出，以便其他线程在获得后得以访问资源。互斥量比临界区复杂。因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享，而且可以在不同应用程序的线程之间实现对资源的安全共享。&nbsp;</span><br style="font-family: Verdana; font-size: 12pt;" /><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;</span><br style="font-family: Verdana; font-size: 12pt;" /><span style="font-family: Verdana; font-size: 12pt;">　　互斥量包含的几个操作原语：&nbsp;</span><br style="font-family: Verdana; font-size: 12pt;" /><span style="font-family: Verdana; font-size: 12pt;">　　CreateMutex（） 创建一个互斥量&nbsp;</span><br style="font-family: Verdana; font-size: 12pt;" /><span style="font-family: Verdana; font-size: 12pt;">　　OpenMutex（） 打开一个互斥量&nbsp;</span><br style="font-family: Verdana; font-size: 12pt;" /><span style="font-family: Verdana; font-size: 12pt;">　　ReleaseMutex（） 释放互斥量&nbsp;</span><br style="font-family: Verdana; font-size: 12pt;" /><span style="font-family: Verdana; font-size: 12pt;">　　WaitForMultipleObjects（） 等待互斥量对象&nbsp;</span><br style="font-family: Verdana; font-size: 12pt;" /><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;</span><br style="font-family: Verdana; font-size: 12pt;" /><span style="font-family: Verdana; font-size: 12pt;">　　同样MFC为互斥量提供有一个CMutex类。使用CMutex类实现互斥量操作非常简单，但是要特别注意对CMutex的构造函数的调用&nbsp;</span><br style="font-family: Verdana; font-size: 12pt;" /><span style="font-family: Verdana; font-size: 12pt;">　　CMutex( BOOL bInitiallyOwn = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL)&nbsp;</span><br style="font-family: Verdana; font-size: 12pt;" /><span style="font-family: Verdana; font-size: 12pt;">　　不用的参数不能乱填，乱填会出现一些意想不到的运行结果。&nbsp;</span><br style="font-family: Verdana; font-size: 12pt;" /><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;&nbsp;</span><br style="font-family: Verdana; font-size: 12pt;" /><span style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;</span><span style="font-size: 13px; color: #008000;">//</span><span style="font-size: 13px; color: #008000;">创建互斥量&nbsp;</span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all">&nbsp;&nbsp;CMutex&nbsp;global_Mutex(0,0,0);&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;共享资源&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;global_Array[256];&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;InitializeArray()&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;i&lt;256;i++)&nbsp;<br />&nbsp;&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;global_Array[i]=I;&nbsp;<br />&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;UINT&nbsp;Global_ThreadWrite(LPVOID&nbsp;pParam)&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;CEdit&nbsp;*ptr=(CEdit&nbsp;*)pParam;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText("");&nbsp;<br />&nbsp;&nbsp;&nbsp;global_Mutex.Lock();&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;i&lt;256;i++)&nbsp;<br />&nbsp;&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;global_Array[i]=W;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText(global_Array);&nbsp;<br />&nbsp;&nbsp;&nbsp;Sleep(10);&nbsp;<br />&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;global_Mutex.Unlock();&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;&nbsp;<br />&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;UINT&nbsp;Global_ThreadDelete(LPVOID&nbsp;pParam)&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;CEdit&nbsp;*ptr=(CEdit&nbsp;*)pParam;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText("");&nbsp;<br />&nbsp;&nbsp;&nbsp;global_Mutex.Lock();&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;i&lt;256;i++)&nbsp;<br />&nbsp;&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;global_Array[i]=D;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText(global_Array);&nbsp;<br />&nbsp;&nbsp;&nbsp;Sleep(10);&nbsp;<br />&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;global_Mutex.Unlock();&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;&nbsp;<br />&nbsp;&nbsp;}&nbsp;</div><span style="font-family: Verdana; font-size: 12pt;">　　</span><span style="font-family: Verdana; font-size: 12pt;">同样在测试程序中，Lock UnLock两个按钮分别实现，在有互斥量保护共享资源的执行状态，和没有互斥量保护共享资源的执行状态。</span><p style="font-family: Verdana; font-size: 12pt;">&nbsp;&nbsp;　　</p><p style="font-family: Verdana; font-size: 12pt;"><strong>信号量（Semaphores）</strong></p><p style="font-family: Verdana; font-size: 12pt;"><br />　　信号量对象对线程的同步方式与前面几种方法不同，信号允许多个线程同时使用共享资源，这与操作系统中的PV操作相同。它指出了同时访问共享资源的线程最大数目。它允许多个线程在同一时刻访问同一资源，但是需要限制在同一时刻访问此资源的最大线程数目。在用CreateSemaphore（）创建信号量时即要同时指出允许的最大资源计数和当前可用资源计数。一般是将当前可用资源计数设置为最大资源计数，每增加一个线程对共享资源的访问，当前可用资源计数就会减1，只要当前可用资源计数是大于0的，就可以发出信号量信号。但是当前可用计数减小到0时则说明当前占用资源的线程数已经达到了所允许的最大数目，不能在允许其他线程的进入，此时的信号量信号将无法发出。线程在处理完共享资源后，应在离开的同时通过ReleaseSemaphore（）函数将当前可用资源计数加1。在任何时候当前可用资源计数决不可能大于最大资源计数。&nbsp;<br />　　PV操作及信号量的概念都是由荷兰科学家E.W.Dijkstra提出的。信号量S是一个整数，S大于等于零时代表可供并发进程使用的资源实体数，但S小于零时则表示正在等待使用共享资源的进程数。&nbsp;<br />　　P操作 申请资源：&nbsp;<br />&nbsp;&nbsp;　　（1）S减1；&nbsp;<br />&nbsp;&nbsp;　　（2）若S减1后仍大于等于零，则进程继续执行；&nbsp;<br />&nbsp;&nbsp;　　（3）若S减1后小于零，则该进程被阻塞后进入与该信号相对应的队列中，然后转入进程调度。&nbsp;<br />&nbsp;&nbsp;V操作 释放资源：&nbsp;<br />&nbsp;&nbsp;　　（1）S加1；&nbsp;<br />&nbsp;&nbsp;　　（2）若相加结果大于零，则进程继续执行；&nbsp;<br />&nbsp;&nbsp;　　（3）若相加结果小于等于零，则从该信号的等待队列中唤醒一个等待进程，然后再返回原进程继续执行或转入进程调度。&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;　　信号量包含的几个操作原语：&nbsp;<br />&nbsp;&nbsp;　　CreateSemaphore（） 创建一个信号量&nbsp;<br />&nbsp;&nbsp;　　OpenSemaphore（） 打开一个信号量&nbsp;<br />&nbsp;&nbsp;　　ReleaseSemaphore（） 释放信号量&nbsp;<br />&nbsp;&nbsp;　　WaitForSingleObject（） 等待信号量&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;<span style="background-color: #eeeeee; font-size: 13px;">&nbsp;</span><span style="font-size: 13px; color: #008000;">//</span><span style="font-size: 13px; color: #008000;">信号量句柄&nbsp;</span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all">&nbsp;&nbsp;HANDLE&nbsp;global_Semephore;&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;共享资源&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;global_Array[256];&nbsp;<br />&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;InitializeArray()&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;i&lt;256;i++)&nbsp;<br />&nbsp;&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;global_Array[i]=I;&nbsp;<br />&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">线程1&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;UINT&nbsp;Global_ThreadOne(LPVOID&nbsp;pParam)&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;CEdit&nbsp;*ptr=(CEdit&nbsp;*)pParam;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText("");&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">等待对共享资源请求被通过&nbsp;等于&nbsp;P操作&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;WaitForSingleObject(global_Semephore,&nbsp;INFINITE);&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;i&lt;256;i++)&nbsp;<br />&nbsp;&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;global_Array[i]=O;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText(global_Array);&nbsp;<br />&nbsp;&nbsp;&nbsp;Sleep(10);&nbsp;<br />&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">释放共享资源&nbsp;等于&nbsp;V操作&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;ReleaseSemaphore(global_Semephore,&nbsp;1,&nbsp;NULL);&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;&nbsp;<br />&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;UINT&nbsp;Global_ThreadTwo(LPVOID&nbsp;pParam)&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;CEdit&nbsp;*ptr=(CEdit&nbsp;*)pParam;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText("");&nbsp;<br />&nbsp;&nbsp;&nbsp;WaitForSingleObject(global_Semephore,&nbsp;INFINITE);&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;i&lt;256;i++)&nbsp;<br />&nbsp;&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;global_Array[i]=T;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText(global_Array);&nbsp;<br />&nbsp;&nbsp;&nbsp;Sleep(10);&nbsp;<br />&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;ReleaseSemaphore(global_Semephore,&nbsp;1,&nbsp;NULL);&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;&nbsp;<br />&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;UINT&nbsp;Global_ThreadThree(LPVOID&nbsp;pParam)&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;CEdit&nbsp;*ptr=(CEdit&nbsp;*)pParam;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText("");&nbsp;<br />&nbsp;&nbsp;&nbsp;WaitForSingleObject(global_Semephore,&nbsp;INFINITE);&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;i&lt;256;i++)&nbsp;<br />&nbsp;&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;global_Array[i]=H;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText(global_Array);&nbsp;<br />&nbsp;&nbsp;&nbsp;Sleep(10);&nbsp;<br />&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;ReleaseSemaphore(global_Semephore,&nbsp;1,&nbsp;NULL);&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;&nbsp;<br />&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;CSemaphoreDlg::OnBnClickedButtonOne()&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">设置信号量&nbsp;1&nbsp;个资源&nbsp;1同时只可以有一个线程访问&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;global_Semephore=&nbsp;CreateSemaphore(NULL,&nbsp;1,&nbsp;1,&nbsp;NULL);&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">this</span>-&gt;StartThread();&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;TODO:&nbsp;Add&nbsp;your&nbsp;control&nbsp;notification&nbsp;handler&nbsp;code&nbsp;here&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;CSemaphoreDlg::OnBnClickedButtonTwo()&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">设置信号量&nbsp;2&nbsp;个资源&nbsp;2&nbsp;同时只可以有两个线程访问&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;global_Semephore=&nbsp;CreateSemaphore(NULL,&nbsp;2,&nbsp;2,&nbsp;NULL);&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">this</span>-&gt;StartThread();&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;TODO:&nbsp;Add&nbsp;your&nbsp;control&nbsp;notification&nbsp;handler&nbsp;code&nbsp;here&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;CSemaphoreDlg::OnBnClickedButtonThree()&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">设置信号量&nbsp;3&nbsp;个资源&nbsp;3&nbsp;同时只可以有三个线程访问&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;global_Semephore=&nbsp;CreateSemaphore(NULL,&nbsp;3,&nbsp;3,&nbsp;NULL);&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">this</span>-&gt;StartThread();&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;TODO:&nbsp;Add&nbsp;your&nbsp;control&nbsp;notification&nbsp;handler&nbsp;code&nbsp;here&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;}&nbsp;</div>　<span style="font-size: 12pt;">　信号量的使用特点使其更适用于对Socket（套接字）程序中线程的同步。例如，网络上的HTTP服务器要对同一时间内访问同一页面的用户数加以限制，这时可以为每一个用户对服务器的页面请求设置一个线程，而页面则是待保护的共享资源，通过使用信号量对线程的同步作用可以确保在任一时刻无论有多少用户对某一页面进行访问，只有不大于设定的最大用户数目的线程能够进行访问，而其他的访问企图则被挂起，只有在有用户退出对此页面的访问后才有可能进入。&nbsp;</span><br />&nbsp;&nbsp;　　<p>&nbsp;</p><p style="font-family: Verdana; font-size: 12pt;"><strong>事件（Event）</strong>&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />　　事件对象也可以通过通知操作的方式来保持线程的同步。并且可以实现不同进程中的线程同步操作。&nbsp;<br />　　信号量包含的几个操作原语：&nbsp;<br />&nbsp;&nbsp;　　CreateEvent（） 创建一个信号量&nbsp;<br />&nbsp;&nbsp;　　OpenEvent（） 打开一个事件&nbsp;<br />&nbsp;&nbsp;　　SetEvent（） 回置事件&nbsp;<br />&nbsp;&nbsp;　　WaitForSingleObject（） 等待一个事件&nbsp;<br />&nbsp;&nbsp;　　WaitForMultipleObjects（）　　　　　　　　 等待多个事件&nbsp;<br />&nbsp;&nbsp;　　　　WaitForMultipleObjects 函数原型：&nbsp;<br />&nbsp;&nbsp;　　　　　WaitForMultipleObjects（&nbsp;<br />&nbsp;&nbsp;　　　　　IN DWORD nCount, // 等待句柄数&nbsp;<br />&nbsp;&nbsp;　　　　　IN CONST HANDLE *lpHandles, //指向句柄数组&nbsp;<br />&nbsp;&nbsp;　　　　　IN BOOL bWaitAll, //是否完全等待标志&nbsp;<br />&nbsp;&nbsp;　　　　　IN DWORD dwMilliseconds //等待时间&nbsp;<br />&nbsp;&nbsp;　　　　　）&nbsp;<br />　　参数nCount指定了要等待的内核对象的数目，存放这些内核对象的数组由lpHandles来指向。fWaitAll对指定的这nCount个内核对象的两种等待方式进行了指定，为TRUE时当所有对象都被通知时函数才会返回，为FALSE则只要其中任何一个得到通知就可以返回。dwMilliseconds在这里的作用与在WaitForSingleObject（）中的作用是完全一致的。如果等待超时，函数将返回WAIT_TIMEOUT。&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;<span style="background-color: #eeeeee; font-size: 13px;">&nbsp;</span><span style="font-size: 13px; color: #008000;">//</span><span style="font-size: 13px; color: #008000;">事件数组&nbsp;</span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all">&nbsp;&nbsp;HANDLE&nbsp;global_Events[2];&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;共享资源&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;global_Array[256];&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;InitializeArray()&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;i&lt;256;i++)&nbsp;<br />&nbsp;&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;global_Array[i]=I;&nbsp;<br />&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;UINT&nbsp;Global_ThreadOne(LPVOID&nbsp;pParam)&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;CEdit&nbsp;*ptr=(CEdit&nbsp;*)pParam;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText("");&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;i&lt;256;i++)&nbsp;<br />&nbsp;&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;global_Array[i]=O;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText(global_Array);&nbsp;<br />&nbsp;&nbsp;&nbsp;Sleep(10);&nbsp;<br />&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">回置事件&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;SetEvent(global_Events[0]);&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;&nbsp;<br />&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;UINT&nbsp;Global_ThreadTwo(LPVOID&nbsp;pParam)&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;CEdit&nbsp;*ptr=(CEdit&nbsp;*)pParam;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText("");&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;i&lt;256;i++)&nbsp;<br />&nbsp;&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;global_Array[i]=T;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText(global_Array);&nbsp;<br />&nbsp;&nbsp;&nbsp;Sleep(10);&nbsp;<br />&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">回置事件&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;SetEvent(global_Events[1]);&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;&nbsp;<br />&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;UINT&nbsp;Global_ThreadThree(LPVOID&nbsp;pParam)&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;CEdit&nbsp;*ptr=(CEdit&nbsp;*)pParam;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText("");&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">等待两个事件都被回置&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;WaitForMultipleObjects(2,&nbsp;global_Events,&nbsp;<span style="color: #0000FF; ">true</span>,&nbsp;INFINITE);&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;i&lt;256;i++)&nbsp;<br />&nbsp;&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;global_Array[i]=H;&nbsp;<br />&nbsp;&nbsp;&nbsp;ptr-&gt;SetWindowText(global_Array);&nbsp;<br />&nbsp;&nbsp;&nbsp;Sleep(10);&nbsp;<br />&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;&nbsp;<br />&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;CEventDlg::OnBnClickedButtonStart()&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;2;&nbsp;i++)&nbsp;<br />&nbsp;&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">实例化事件&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;global_Events[i]=CreateEvent(NULL,<span style="color: #0000FF; ">false</span>,<span style="color: #0000FF; ">false</span>,NULL);&nbsp;<br />&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;CWinThread&nbsp;*ptrOne&nbsp;=&nbsp;AfxBeginThread(Global_ThreadOne,&nbsp;<br />&nbsp;&nbsp;&nbsp;&amp;m_One,&nbsp;<br />&nbsp;&nbsp;&nbsp;THREAD_PRIORITY_NORMAL,&nbsp;<br />&nbsp;&nbsp;&nbsp;0,&nbsp;<br />&nbsp;&nbsp;&nbsp;CREATE_SUSPENDED);&nbsp;<br />&nbsp;&nbsp;&nbsp;ptrOne-&gt;ResumeThread();&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">Start&nbsp;the&nbsp;second&nbsp;Thread&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;CWinThread&nbsp;*ptrTwo&nbsp;=&nbsp;AfxBeginThread(Global_ThreadTwo,&nbsp;<br />&nbsp;&nbsp;&nbsp;&amp;m_Two,&nbsp;<br />&nbsp;&nbsp;&nbsp;THREAD_PRIORITY_NORMAL,&nbsp;<br />&nbsp;&nbsp;&nbsp;0,&nbsp;<br />&nbsp;&nbsp;&nbsp;CREATE_SUSPENDED);&nbsp;<br />&nbsp;&nbsp;&nbsp;ptrTwo-&gt;ResumeThread();&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">Start&nbsp;the&nbsp;Third&nbsp;Thread&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;CWinThread&nbsp;*ptrThree&nbsp;=&nbsp;AfxBeginThread(Global_ThreadThree,&nbsp;<br />&nbsp;&nbsp;&nbsp;&amp;m_Three,&nbsp;<br />&nbsp;&nbsp;&nbsp;THREAD_PRIORITY_NORMAL,&nbsp;<br />&nbsp;&nbsp;&nbsp;0,&nbsp;<br />&nbsp;&nbsp;&nbsp;CREATE_SUSPENDED);&nbsp;<br />&nbsp;&nbsp;&nbsp;ptrThree-&gt;ResumeThread();&nbsp;<br />&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;TODO:&nbsp;Add&nbsp;your&nbsp;control&nbsp;notification&nbsp;handler&nbsp;code&nbsp;here&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;}&nbsp;</div>　　<span style="font-size: 12pt;">事件可以实现不同进程中的线程同步操作，并且可以方便的实现多个线程的优先比较等待操作，例如写多个WaitForSingleObject来代替WaitForMultipleObjects从而使编程更加灵活。&nbsp;</span><br />　　<p>&nbsp;</p><p style="font-family: Verdana; font-size: 12pt;"><strong>总结：</strong>&nbsp;<br />　　1． 互斥量与临界区的作用非常相似，但互斥量是可以命名的，也就是说它可以跨越进程使用。所以创建互斥量需要的资源更多，所以如果只为了在进程内部是用的话使用临界区会带来速度上的优势并能够减少资源占用量。因为互斥量是跨进程的互斥量一旦被创建，就可以通过名字打开它。&nbsp;<br />　　2． 互斥量（Mutex），信号灯（Semaphore），事件（Event）都可以被跨越进程使用来进行同步数据操作，而其他的对象与数据同步操作无关，但对于进程和线程来讲，如果进程和线程在运行状态则为无信号状态，在退出后为有信号状态。所以可以使用WaitForSingleObject来等待进程和线程退出。&nbsp;<br />　　3． 通过互斥量可以指定资源被独占的方式使用，但如果有下面一种情况通过互斥量就无法处理，比如现在一位用户购买了一份三个并发访问许可的数据库系统，可以根据用户购买的访问许可数量来决定有多少个线程/进程能同时进行数据库操作，这时候如果利用互斥量就没有办法完成这个要求，信号灯对象可以说是一种资源计数器。&nbsp;<br /></p><p style="font-family: Verdana; font-size: 12pt;"><strong>疑问：</strong>&nbsp;<br />　　在 Linux 上，有两类信号量。第一类是由 semget/semop/semctl API 定义的信号量的 SVR4（System V Release 4）版本。第二类是由 sem_init/sem_wait/sem_post/interfaces 定义的 POSIX 接口。 它们具有相同的功能，但接口不同。 在2.4.x内核中，信号量数据结构定义为(include/asm/semaphore.h)。&nbsp;<br />　　但是在Linux中没有对互斥量的具体提法，只是看到说互斥量是信号量的一种特殊情况，当信号量的最大资源数=1同时可以访问共享资源的线程数=1 就是互斥量了。临界区的定义也比较模糊。没有找到用事件处理线程/进程同步互斥的操作的相关资料。在Linux下用GCC/G++编译标准C++代码，信号量的操作几乎和Windows下VC7的编程一样，不用改多少就顺利移植了，可是互斥量，事件，临界区的Linux移植没有成功。&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />　　本文所有事例程序在WindowsXp Sp2 + VC7 下编译通过。<br /><br />本文转自：<a href="http://www.bccn.net/Article/kfyy/vc/jszl/200709/6380_2.html">http://www.bccn.net/Article/kfyy/vc/jszl/200709/6380_2.html</a></p><p>&nbsp;</p><p>&nbsp;</p><img src ="http://www.cppblog.com/wanghaiguang/aggbug/199549.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2013-04-18 17:06 <a href="http://www.cppblog.com/wanghaiguang/archive/2013/04/18/199549.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于typedef的用法总结（转载）</title><link>http://www.cppblog.com/wanghaiguang/archive/2013/02/20/197957.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Wed, 20 Feb 2013 09:19:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2013/02/20/197957.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/197957.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2013/02/20/197957.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/197957.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/197957.html</trackback:ping><description><![CDATA[<p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">&nbsp; &nbsp;不管实在C还是C++代码中，typedef这个词都不少见，当然出现频率较高的还是在C代码中。typedef与#define有些相似，但更多的是不同，特别是在一些复杂的用法上，就完全不同了，看了网上一些C/C++的学习者的博客，其中有一篇关于typedef的总结还是很不错，由于总结的很好，我就不加修改的引用过来了，以下是引用的内容(</span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: red; font-size: 12pt;">红色部分是我自己写的内容</span><span style="font-size: 12pt;">)。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体; font-size: 12pt;">用途一：</span></strong></p><p align="left" style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体; font-size: 12pt;">定义一种类型的别名，而不只是简单的宏替换。可以用作同时声明指针型的多个对象。比如：</span></p><p align="left" style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">char* pa, pb;&nbsp;//&nbsp;</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体; font-size: 12pt;">这多数不符合我们的意图，它只声明了一个指向字符变量的指针，</span></p><p align="left" style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">//&nbsp;</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体; font-size: 12pt;">和一个字符变量；</span></p><p align="left" style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体; font-size: 12pt;">以下则可行：</span></p><p align="left" style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">typedef char* PCHAR;</span></p><p align="left" style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">PCHAR pa, pb;&nbsp;&nbsp;</span></p><p align="left" style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe; color: red;"><span style="font-size: 12pt;">这种用法很有用，特别是char* pa, pb的定义，初学者往往认为是定义了两个字符型指针，其实不是，而用typedef char* PCHAR就不会出现这样的问题，减少了错误的发生。</span></p><p align="left" style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe; color: red;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #333300; font-size: 12pt;">用途二:<br style="margin: 0px; padding: 0px;" /></span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #333300; font-size: 12pt;">用在旧的C代码中，帮助struct。以前的代码中，声明struct新对象时，必须要带上</span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">struct，即形式为： struct 结构名对象名，如：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">struct tagPOINT1</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">&nbsp;{</span><br style="margin: 0px; padding: 0px;" /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp; int x;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp; int y;&nbsp;</span><br style="margin: 0px; padding: 0px;" /><span style="font-size: 12pt;">};</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">struct tagPOINT1 p1;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">而在C++中，则可以直接写：结构名对象名，即：tagPOINT1 p1;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">typedef struct tagPOINT</span><br style="margin: 0px; padding: 0px;" /><span style="font-size: 12pt;">{</span><br style="margin: 0px; padding: 0px;" /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp; int x;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp; int y;</span><br style="margin: 0px; padding: 0px;" /><span style="font-size: 12pt;">}POINT;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">POINT p1; // 这样就比原来的方式少写了一个struct，比较省事，尤其在大量使用的时</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">候,或许，在C++中，typedef的这种用途二不是很大，但是理解了它，对掌握以前的旧代</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">码还是有帮助的，毕竟我们在项目中有可能会遇到较早些年代遗留下来的代码。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">用途三：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">用typedef来定义与平台无关的类型。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">比如定义一个叫 REAL 的浮点类型，在目标平台一上，让它表示最高精度的类型为：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">typedef long double REAL;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">在不支持 long double 的平台二上，改为：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">typedef double REAL;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">在连 double 都不支持的平台三上，改为：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">typedef float REAL;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">也就是说，当跨平台时，只要改下 typedef 本身就行，不用对其他源码做任何修改。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="font-size: 12pt;">标准库就广泛使用了这个技巧，比如size_t。另外，因为typedef是定义了一种类型的新别名，不是简单的字符串替换，所以它比宏来得稳健。</span><br style="margin: 0px; padding: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;<span style="margin: 0px; padding: 0px; line-height: 1.5; color: #ff0000; font-size: 12pt;">&nbsp;这个优点在我们写代码的过程中可以减少不少代码量哦！</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; background-color: #f5fafe;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #ff0000;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">用途四：</span></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">为复杂的声明定义一个新的简单的别名。方法是：在原来的声明里逐步用别名替换一部</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">分复杂声明，如此循环，把带变量名的部分留到最后替换，得到的就是原声明的最简化</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">版。举例：&nbsp;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;原声明：void (*b[10]) (void (*)());</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">变量名为b，先替换右边部分括号里的，pFunParam为别名一：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">typedef void (*pFunParam)();</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">再替换左边的变量b，pFunx为别名二：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">typedef void (*pFunx)(pFunParam);</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">原声明的最简化版：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">pFunx b[10];<br style="margin: 0px; padding: 0px;" />&nbsp;<br style="margin: 0px; padding: 0px;" /></span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">原声明：doube(*)() (*e)[9];</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">变量名为e，先替换左边部分，pFuny为别名一：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">typedef double(*pFuny)();</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">再替换右边的变量e，pFunParamy为别名二</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">typedef pFuny (*pFunParamy)[9];</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">原声明的最简化版：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">pFunParamy e;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">理解复杂声明可用的&#8220;右左法则&#8221;：从变量名看起，先往右，再往左，碰到一个圆括号</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">就调转阅读的方向；括号内分析完就跳出括号，还是按先右后左的顺序，如此循环，直</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">到整个声明分析完。举例：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">int (*func)(int *p);</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">首先找到变量名func，外面有一对圆括号，而且左边是一个*号，这说明func是一个指针</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">；然后跳出这个圆括号，先看右边，又遇到圆括号，这说明(*func)是一个函数，所以</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">func是一个指向这类函数的指针，即函数指针，这类函数具有int*类型的形参，返回值</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">类型是int。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">int (*func[5])(int *);</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">func右边是一个[]运算符，说明func是具有5个元素的数组；func的左边有一个*，说明</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">func的元素是指针（注意这里的*不是修饰func，而是修饰func[5]的，原因是[]运算符</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">优先级比*高，func先跟[]结合）。跳出这个括号，看右边，又遇到圆括号，说明func数</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">组的元素是函数类型的指针，它指向的函数具有int*类型的形参，返回值类型为int。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300;"><span style="margin: 0px; padding: 0px; line-height: 1.5;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #ff0000; font-size: 12pt;">这种用法是比较复杂的，出现的频率也不少，往往在看到这样的用法却不能理解，相信以上的解释能有所帮助。</span></span></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">*****以上为参考部分，以下为本人领悟部分*****</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">使用示例：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">1.比较一：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">#include &lt;iostream&gt;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">using namespace std;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">typedef int (*A) (char, char);</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">int ss(char a, char b)<br style="margin: 0px; padding: 0px;" /></span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">{<br style="margin: 0px; padding: 0px;" /></span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;&nbsp;&nbsp; cout&lt;&lt;"功能1"&lt;&lt;endl;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;&nbsp;&nbsp; cout&lt;&lt;a&lt;&lt;endl;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;&nbsp;&nbsp; cout&lt;&lt;b&lt;&lt;endl;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;&nbsp;&nbsp; return 0;<br style="margin: 0px; padding: 0px;" /></span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">}<br style="margin: 0px; padding: 0px;" />&nbsp;<br style="margin: 0px; padding: 0px;" /></span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">int bb(char a, char b)<br style="margin: 0px; padding: 0px;" /></span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">{</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;&nbsp;&nbsp; cout&lt;&lt;"功能2"&lt;&lt;endl;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;&nbsp;&nbsp; cout&lt;&lt;b&lt;&lt;endl;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;&nbsp;&nbsp; cout&lt;&lt;a&lt;&lt;endl;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;&nbsp;&nbsp; return 0;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">}</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">void main()<br style="margin: 0px; padding: 0px;" /></span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">{</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;&nbsp;&nbsp; A a;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;&nbsp;&nbsp; a = ss;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;&nbsp;&nbsp; a('a','b');</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;&nbsp;&nbsp; a = bb;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;&nbsp;&nbsp; a('a', 'b');<br style="margin: 0px; padding: 0px;" /></span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">}</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">2.比较二：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">typedef int (A) (char, char);</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">void main()<br style="margin: 0px; padding: 0px;" /></span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">{</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;&nbsp;&nbsp; A *a;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;&nbsp;&nbsp; a = ss;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;&nbsp;&nbsp; a('a','b');</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;&nbsp;&nbsp; a = bb;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">&nbsp;&nbsp;&nbsp; a('a','b');<br style="margin: 0px; padding: 0px;" /></span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">}<br style="margin: 0px; padding: 0px;" />&nbsp;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">两个程序的结果都一样：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">功能1</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">a</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">b</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">功能2</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">b</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">a</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">*****以下是参考部分*****</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">参考自：http://blog.hc360.com/portal/personShowArticle.do?articleId=57527</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">typedef 与 #define的区别：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">案例一：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">通常讲，typedef要比#define要好，特别是在有指针的场合。请看例子：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">typedef char *pStr1;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">#define pStr2 char *;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">pStr1 s1, s2;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">pStr2 s3, s4;<br style="margin: 0px; padding: 0px;" /></span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">在上述的变量定义中，s1、s2、s3都被定义为char *，而s4则定义成了char，不是我们</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">所预期的指针变量，根本原因就在于#define只是简单的字符串替换而typedef则是为一</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">个类型起新名字。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">案例二：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">下面的代码中编译器会报一个错误，你知道是哪个语句错了吗？</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">typedef char * pStr;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">char string[4] = "abc";</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">const char *p1 = string;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">const pStr p2 = string;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">p1++;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">p2++;</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">　　是p2++出错了。这个问题再一次提醒我们：typedef和#define不同，它不是简单的</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">文本替换。上述代码中const pStr p2并不等于const char * p2。const pStr p2和</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">const long x本质上没有区别，都是对变量进行只读限制，只不过此处变量p2的数据类</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">型是我们自己定义的而不是系统固有类型而已。因此，const pStr p2的含义是：限定数</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #003300; font-size: 12pt;">据类型为char *的变量p2为只读，因此p2++错误。<span style="margin: 0px; padding: 0px; line-height: 1.5; color: #ff0000; font-size: 12pt;">虽然作者在这里已经解释得很清楚了，可我在这个地方仍然还是糊涂的，真的希望哪位高手能帮忙指点一下，特别是这一句&#8220;只不过此处变量p2的数据类型是我们自己定义的而不是系统固有类型而已&#8221;，难道自己定义的类型前面用const修饰后，就不能执行更改运算，而系统定义的类型却可以？<br /><br /></span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-size: 12pt;">本文转自：</span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: #ff0000;"></span></span><span style="font-size: 12pt;">http://www.cnblogs.com/csyisong/archive/2009/01/09/1372363.html</span></p><img src ="http://www.cppblog.com/wanghaiguang/aggbug/197957.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2013-02-20 17:19 <a href="http://www.cppblog.com/wanghaiguang/archive/2013/02/20/197957.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>与 或 非 异或</title><link>http://www.cppblog.com/wanghaiguang/archive/2013/01/18/197381.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Fri, 18 Jan 2013 03:07:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2013/01/18/197381.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/197381.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2013/01/18/197381.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/197381.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/197381.html</trackback:ping><description><![CDATA[<div id="article_content" style="margin: 20px 0px 0px; line-height: 26px; font-family: Arial; color: #333333; background-color: #ffffff;"><p>说说异或运算^和他的一个常用作用。<br />异或的运算方法是一个二进制运算：<br />1^1=0<br />0^0=0<br />1^0=1<br />0^1=1<br /><br />两者相等为0,不等为1.<br /><br />这样我们发现交换两个整数的值时可以不用第三个参数。<br />如a=11,b=9.以下是二进制<br />a=a^b=1011^1001=0010;<br />b=b^a=1001^0010=1011;<br />a=a^b=0010^1011=1001;<br />这样一来a=9,b=13了。<br /><br /><br />举一个运用，	按一个按钮交换两个mc的位置可以这样。<br /><br />mybt.onPress=function()<br />{<br />mc1._x=mc1._x^mc2._x;<br />mc2._x=mc2._x^mc1._x;<br />mc1._x=mc1._x^mc2._x;<br />//<br />mc1._y=mc1._y^mc2._y;	<br />mc2._y=mc2._y^mc1._y;<br />mc1._y=mc1._y^mc2._y;<br />}<br /><br />这样就可以不通过监时变量来传递了。<br /><br />最后要声明：只能用于整数。</p><p>&nbsp;</p><h2>1.&nbsp;位运算&nbsp;<a href="http://learn.akae.cn/akabook/ch16s01_1" target="_blank" style="color: #336699; text-decoration: initial;"><span style="font-size: medium;">请点评</span></a></h2><p>整数在计算机中用二进制的位来表示，C语言提供一些运算符可以直接操作整数中的位，称为位运算，这些运算符的操作数都必须是整型的。在以后的学习中你会发现，有些信息利用整数中的某几个位来存储，要访问这些位，仅仅有对整数的操作是不够的，必须借助位运算，例如<a href="http://learn.akae.cn/media/apas02.html#app-encoding.utf8" style="color: #336699; text-decoration: initial;">第&nbsp;2&nbsp;节 &#8220;Unicode和UTF-8&#8221;</a>&nbsp;介绍的UTF-8编码就是如此，学完本节之后你应该能自己写出UTF-8的编码和解码程序。本节首先介绍各种位运算符，然后介绍与位运算有关的编程技巧。</p><div xml:lang="zh-cn"><div><h3>1.1.&nbsp;按位与、或、异或、取反运算&nbsp;<a href="http://learn.akae.cn/akabook/ch16s01_2" target="_blank" style="color: #336699; text-decoration: initial;"><span style="font-size: medium;">请点评</span></a></h3></div><p>在<a href="http://learn.akae.cn/media/ch04s03.html#cond.bool" style="color: #336699; text-decoration: initial;">第&nbsp;3&nbsp;节 &#8220;布尔代数&#8221;</a>&nbsp;讲过逻辑与、或、非运算，并列出了真值表，对于整数中的位也可以做与、或、非运算，C语言提供了按位与（Bitwise AND）运算符&amp;、按位或（Bitwise OR）运算符|和按位取反（Bitwise NOT）运算符~，此外还有按位异或（Bitwise XOR）运算符^，我们在<a href="http://learn.akae.cn/media/ch14s01.html#number.binary" style="color: #336699; text-decoration: initial;">第&nbsp;1&nbsp;节 &#8220;为什么计算机用二进制计数&#8221;</a>&nbsp;讲过异或运算。下面用二进制的形式举几个例子。</p><div><p><strong>图&nbsp;16.1.&nbsp;位运算</strong></p><div><img src="http://learn.akae.cn/media/images/op.bitwise.png" alt="位运算" style="border: none;" /></div></div><br /><p>注 意，&amp;、|、^运算符都是要做Usual Arithmetic Conversion的（其中有一步是Integer Promotion），~运算符也要做Integer Promotion，所以在C语言中其实并不存在8位整数的位运算，操作数在做位运算之前都至少被提升为<code>int</code>&nbsp;型了，上面用8位整数举例只是为了书写方便。比如：</p><pre name="code" style="white-space: pre-wrap; word-wrap: break-word;">unsigned char c = 0xfc;<br /> unsigned int i = ~c;</pre><p>计算过程是这样的：常量0xfc是<code>int</code>&nbsp;型的，赋给<code>c</code>&nbsp;要转成<code>unsigned char</code>&nbsp;，值不变；<code>c</code>&nbsp;的十六进制表示是fc，计算<code>~c</code>&nbsp;时先提升为整型（000000fc）然后取反，最后结果是ffffff03。注意，如果把<code>~c</code>&nbsp;看成是8位整数的取反，最后结果就得3了，这就错了。为了避免出错，一是尽量避免不同类型之间的赋值，二是每一步计算都要按上一章讲的类型转换规则仔细检查。</p></div><div xml:lang="zh-cn"><div><h3>1.2.&nbsp;移位运算&nbsp;<a href="http://learn.akae.cn/akabook/ch16s01_3" target="_blank" style="color: #336699; text-decoration: initial;"><span style="font-size: medium;">请点评</span></a></h3></div><p>移位运算符（Bitwise Shift）包括左移&lt;&lt;和右移&gt;&gt;。左移将一个整数的各二进制位全部左移若干位，例如0xcfffffff3&lt;&lt;2得到0x3fffffcc：</p><div><p><strong>图&nbsp;16.2.&nbsp;左移运算</strong></p><div><img src="http://learn.akae.cn/media/images/op.shiftleft.png" alt="左移运算" style="border: none;" /></div></div><br /><p>最高两位的11被移出去了，最低两位又补了两个0，其它位依次左移两位。但要注意，移动的位数必须小于左操作数的总位数，比如上面的例子，左边是<code>unsigned int</code>&nbsp;型，如果左移的位数大于等于32位，则结果是Undefined。移位运算符不同于+ - * / ==等运算符，两边操作数的类型不要求一致，但两边操作数都要做Integer Promotion，整个表达式的类型和左操作数提升后的类型相同。</p><p>复习一下<a href="http://learn.akae.cn/media/ch14s02.html#number.convert" style="color: #336699; text-decoration: initial;">第&nbsp;2&nbsp;节 &#8220;不同进制之间的换算&#8221;</a>&nbsp;讲过的知识可以得出结论，<em>在一定的取值范围内，将一个整数左移1位相当于乘以2</em>&nbsp;。比如二进制11（十进制3）左移一位变成110，就是6，再左移一位变成1100，就是12。读者可以自己验证这条规律对有符号数和无符号数都成立，对负数也成立。当然，如果左移改变了最高位（符号位），那么结果肯定不是乘以2了，所以我加了个前提&#8220;在一定的取值范围内&nbsp;&#8221;。由于计算机做移位比做乘法快得多，编译器可以利用这一点做优化，比如看到源代码中有<code>i * 8</code>&nbsp;，可以编译成移位指令而不是乘法指令。</p><p>当操作数是无符号数时，右移运算的规则和左移类似，例如0xcfffffff3&gt;&gt;2得到0x33fffffc：</p><div><p><strong>图&nbsp;16.3.&nbsp;右移运算</strong></p><div><img src="http://learn.akae.cn/media/images/op.shiftright.png" alt="右移运算" style="border: none;" /></div></div><br /><p>最低两位的11被移出去了，最高两位又补了两个0，其它位依次右移两位。和左移类似，移动的位数也必须小于左操作数的总位数，否则结果是Undefined。在一定的取值范围内，将一个整数右移1位相当于除以2，小数部分截掉。</p><p>当操作数是有符号数时，右移运算的规则比较复杂：</p><div><ul type="disc"><li><p>如果是正数，那么高位移入0</p></li><li><p>如果是负数，那么高位移入1还是0不一定，这是Implementation-defined的。对于x86平台的<code>gcc</code>&nbsp;编译器，最高位移入1，也就是仍保持负数的符号位，这种处理方式对负数仍然保持了&#8220;右移1位相当于除以2&nbsp;&#8221;的性质。</p></li></ul></div><p>综上所述，由于类型转换和移位等问题，用有符号数做位运算是很不方便的，所以，<em>建议只对无符号数做位运算，以减少出错的可能</em>&nbsp;。</p><div xml:lang="zh-cn"><div><h4>习题&nbsp;<a href="http://learn.akae.cn/akabook/ch16s01_4" target="_blank" style="color: #336699; text-decoration: initial;"><span style="font-size: medium;">请点评</span></a></h4></div><p>1、下面两行<code>printf</code>&nbsp;打印的结果有何不同？请读者比较分析一下。<code>%x</code>&nbsp;转换说明的含义详见<a href="http://learn.akae.cn/media/ch25s02.html#stdlib.formatio" style="color: #336699; text-decoration: initial;">第&nbsp;2.9&nbsp;节 &#8220;格式化I/O函数&#8221;</a>&nbsp;。</p><pre name="code" style="white-space: pre-wrap; word-wrap: break-word;">int i = 0xcffffff3;<br /> printf("%x/n", 0xcffffff3&gt;&gt;2);<br /> printf("%x/n", i&gt;&gt;2);</pre></div></div><div xml:lang="zh-cn"><div><h3>1.3.&nbsp;掩码&nbsp;<a href="http://learn.akae.cn/akabook/ch16s01_5" target="_blank" style="color: #336699; text-decoration: initial;"><span style="font-size: medium;">请点评</span></a></h3></div><p>如果要对一个整数中的某些位进行操作，怎样表示这些位在整数中的位置呢？可以用掩码（Mask）来表示。比如掩码0x0000ff00表示对一个32位整数的8~15位进行操作，举例如下。</p><p>1、取出8~15位。</p><pre name="code" style="white-space: pre-wrap; word-wrap: break-word;">unsigned int a, b, mask = 0x0000ff00;<br /> a = 0x12345678;<br /> b = (a &amp; mask) &gt;&gt; 8; /* 0x00000056 */</pre><p>这样也可以达到同样的效果：</p><pre name="code" style="white-space: pre-wrap; word-wrap: break-word;">b = (a &gt;&gt; 8) &amp; ~(~0U &lt;&lt; 8);</pre><p>2、将8~15位清0。</p><pre name="code" style="white-space: pre-wrap; word-wrap: break-word;">unsigned int a, b, mask = 0x0000ff00;<br /> a = 0x12345678;<br /> b = a &amp; ~mask; /* 0x12340078 */</pre><p>3、将8~15位置1。</p><pre name="code" style="white-space: pre-wrap; word-wrap: break-word;">unsigned int a, b, mask = 0x0000ff00;<br /> a = 0x12345678;<br /> b = a | mask; /* 0x1234ff78 */</pre><div xml:lang="zh-cn"><div><h4>习题&nbsp;<a href="http://learn.akae.cn/akabook/ch16s01_6" target="_blank" style="color: #336699; text-decoration: initial;"><span style="font-size: medium;">请点评</span></a></h4></div><p>1、统计一个无符号整数的二进制表示中1的个数，函数原型是<code>int countbit(unsigned int x);</code>&nbsp;。</p><p>2、用位操作实现无符号整数的乘法运算，函数原型是<code>unsigned int multiply(unsigned int x, unsigned int y);</code>&nbsp;。例如：(11011)<sub>2</sub>&nbsp;&#215;(10010)<sub>2</sub>&nbsp;=((11011)<sub>2</sub>&nbsp;&lt;&lt;1)+((11011)<sub>2</sub>&nbsp;&lt;&lt;4)。</p><p>3、对一个32位无符号整数做循环右移，函数原型是<code>unsigned int rotate_right(unsigned int x, int n);</code>&nbsp;。所谓循环右移就是把低位移出去的部分再补到高位上去，例如<code>rotate_right(0xdeadbeef, 8)</code>&nbsp;的值应该是0xefdeadbe。</p></div></div><div xml:lang="zh-cn"><div><h3>1.4.&nbsp;异或运算的一些特性&nbsp;<a href="http://learn.akae.cn/akabook/ch16s01_7" target="_blank" style="color: #336699; text-decoration: initial;"><span style="font-size: medium;">请点评</span></a></h3></div><p>1、一个数和自己做异或的结果是0。如果需要一个常数0，x86平台的编译器可能会生成这样的指令：<code>xorl %eax, %eax</code>&nbsp;。不管<code>eax</code>&nbsp;寄存器里的值原来是多少，做异或运算都能得到0，这条指令比同样效果的<code>movl $0, %eax</code>&nbsp;指令快，直接对寄存器做位运算比生成一个立即数再传送到寄存器要快一些。</p><p>2、从异或的真值表可以看出，不管是0还是1，和0做异或保持原值不变，和1做异或得到原值的相反值。可以利用这个特性配合掩码实现某些位的翻转，例如：</p><pre name="code" style="white-space: pre-wrap; word-wrap: break-word;">unsigned int a, b, mask = 1U &lt;&lt; 6;<br /> a = 0x12345678;<br /> b = a ^ mask; /* flip the 6th bit */</pre><p>3、如果a<sub>1</sub>&nbsp;^ a<sub>2</sub>&nbsp;^ a<sub>3</sub>&nbsp;^ ... ^ a<sub>n</sub>&nbsp;的结果是1，则表示a<sub>1</sub>&nbsp;、a<sub>2</sub>&nbsp;、a<sub>3</sub>&nbsp;...a<sub>n</sub>&nbsp;之中1的个数为奇数个，否则为偶数个。这条性质可用于奇偶校验（Parity Check），比如在串口通信过程中，每个字节的数据都计算一个校验位，数据和校验位一起发送出去，这样接收方可以根据校验位粗略地判断接收到的数据是否有误。</p><p>4、x ^ x ^ y == y，因为x ^ x == 0，0 ^ y == y。这个性质有什么用呢？我们来看这样一个问题：交换两个变量的值，不得借助额外的存储空间，所以就不能采用<code>temp = a; a = b; b = temp;</code>&nbsp;的办法了。利用位运算可以这样做交换：</p><pre name="code" style="white-space: pre-wrap; word-wrap: break-word;">a = a ^ b;<br /> b = b ^ a;<br /> a = a ^ b;</pre><p>分析一下这个过程。为了避免混淆，把a和b的初值分别记为a<sub>0</sub>&nbsp;和b<sub>0</sub>&nbsp;。第一行，<code>a = a<sub>0</sub>&nbsp;^ b<sub>0</sub>&nbsp;</code>；第二行，把a的新值代入，得到<code>b = b<sub>0</sub>&nbsp;^ a<sub>0</sub>&nbsp;^ b<sub>0</sub>&nbsp;</code>，等号右边的b<sub>0</sub>&nbsp;相当于上面公式中的x，a<sub>0</sub>&nbsp;相当于y，所以结果为a<sub>0</sub>&nbsp;；第三行，把a和b的新值代入，得到<code>a = a<sub>0</sub>&nbsp;^ b<sub>0</sub>&nbsp;^ a<sub>0</sub>&nbsp;</code>，结果为b<sub>0</sub>&nbsp;。注意这个过程不能把同一个变量自己跟自己交换，而利用中间变量<code>temp</code>&nbsp;则可以交换。</p><div xml:lang="zh-cn"><div><h4>习题&nbsp;<a href="http://learn.akae.cn/akabook/ch16s01_8" target="_blank" style="color: #336699; text-decoration: initial;"><span style="font-size: medium;">请点评</span></a></h4></div><p>1、请在网上查找有关RAID（Redundant Array of Independent Disks，独立磁盘冗余阵列）的资料，理解其实现原理，其实就是利用了本节的性质3和4。</p><p>2、交换两个变量的值，不得借助额外的存储空间，除了本节讲的方法之外你还能想出什么方法？本节讲的方法不能把同一个变量自己跟自己交换，你的方法有没有什么局限性？<br /><br />本文转自：http://blog.csdn.net/yunyuehu/article/details/5408446#t1</p></div></div></div><img src ="http://www.cppblog.com/wanghaiguang/aggbug/197381.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2013-01-18 11:07 <a href="http://www.cppblog.com/wanghaiguang/archive/2013/01/18/197381.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转载~怪^_*兽~博文</title><link>http://www.cppblog.com/wanghaiguang/archive/2013/01/07/197059.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Mon, 07 Jan 2013 02:39:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2013/01/07/197059.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/197059.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2013/01/07/197059.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/197059.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/197059.html</trackback:ping><description><![CDATA[<p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 18pt;"><strong>C++</strong></span></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><strong style="font-size: 12pt;">1、《<a href="http://www.cnblogs.com/ldcsaa/archive/2012/06/13/2546551.html" style="color: #009933; text-decoration: initial;">高性能 Windows Socket 服务端与客户端组件（源代码及测试用例下载）</a>》</strong></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><strong style="font-size: 12pt;">&nbsp; &nbsp; 《<a href="http://www.cnblogs.com/ldcsaa/archive/2012/02/26/2367409.html" style="color: #009933; text-decoration: initial;">基于 IOCP 的通用异步 Windows Socket TCP 高性能服务端组件的设计与实现</a>》</strong></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><strong style="font-size: 12pt;">&nbsp; &nbsp; 《<a href="http://www.cnblogs.com/ldcsaa/archive/2012/02/15/2351756.html" style="color: #009933; text-decoration: initial;">通用异步 Windows Socket TCP 客户端组件的设计与实现</a>》</strong></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　摘要：编写 Windows Socket TCP 客户端其实并不困难，Windows 提供了6种 I/O 通信模型供大家选择。但本座看过很多客户端程序都把 Socket 通信和业务逻辑混在一起，剪不断理还乱。每个程序都 Copy / Parse 类似的代码再进行修改，实在有点情何以堪。因此本座利用一些闲暇时光写了一个基于 IOCP 的通用异步 Windows Socket TCP 高性能服务端组件和一个通用异步 Windows Socket TCP 客户端组件供各位看官参详参详，希望能激发下大家的灵感。</span></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　资源下载地址：</span><a href="http://ldcsaa.googlecode.com/files/socket_server_and_client.zip" style="color: #009933; text-decoration: initial;"><span style="font-size: 12pt;">http://ldcsaa.googlecode.com/files/socket_server_and_client.zip</span></a></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;">&nbsp;</p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><strong style="font-size: 12pt;">2、《<a href="http://www.cnblogs.com/ldcsaa/archive/2012/06/28/2560619.html" style="color: #009933; text-decoration: initial;">Windows C++ 应用程序通用日志组件（组件及测试程序下载）</a>》</strong></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　摘要：编写一个通用的日志组件应该着重考虑三个方面：功能、可用性和性能。下面，本座详细说明在设计日志组件时对这些方面问题的考虑：</span></p><ul style="font-family: Verdana, ����; line-height: normal; background-color: #eeeeee;"><li style="list-style-type: none;"><ul><li><span style="font-size: 12pt;">功能：本日志组件的目的是满足大多数应用程序记录日志的需求 &#8212;&#8212; 把日志输出到文件或发送到应用程序中，并不提供一些复杂但不常用的功能</span></li><li><span style="font-size: 12pt;">可用性：本日志组件着重考虑了可用性，尽量让使用者用起来觉得简便、舒心</span></li><li><span style="font-size: 12pt;">性能：性能是组件是否值得使用的硬指标，本组件从设计到编码的过程都尽量考虑到性能优化</span></li></ul></li></ul><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　资源下载地址：</span><a href="http://ldcsaa.googlecode.com/files/VC_Logger.zip" style="color: #009933; text-decoration: initial;"><span style="font-size: 12pt;">http://ldcsaa.googlecode.com/files/VC_Logger.zip</span></a></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;">&nbsp;</p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><strong style="font-size: 12pt;">3、《<a href="http://www.cnblogs.com/ldcsaa/archive/2012/02/18/2356638.html" style="color: #009933; text-decoration: initial;">如何养成良好的 C++ 编程习惯（一）&#8212;&#8212; 内存管理</a>》</strong></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　摘要：说起 C/C++ 的内存管理似乎令人望而生畏，满屏的 new / delete / malloc / free，OutPut 窗口无尽的 Memory Leak 警告，程序诡异的 0X00000004 指针异常，仿佛回到那一年我们一起哭过的日子，你 Hold 得住吗？其实，现实并没有你想的那么糟糕。只要你付出一点点，花一点点心思，没错！就一点点而已 &#8212;&#8212;&nbsp;</span><strong style="font-size: 12pt;">用 C++ 类封装内存访问</strong>，就会解决你大部分的烦恼，让你受益终身。以 Windows 程序为例，主要有以下几种内存管理方式：</p><ul style="font-family: Verdana, ����; line-height: normal; background-color: #eeeeee;"><li style="list-style-type: none;"><ul><li><strong style="font-size: 12pt;">虚拟内存</strong>（Virtual Memory）</li><li><strong style="font-size: 12pt;">默认堆</strong>和<strong>私有堆</strong>（Process Heap &amp; Private Heap）</li><li><strong style="font-size: 12pt;">内存映射文件</strong>（File Mapping）</li><li><strong style="font-size: 12pt;">进程堆栈</strong>（Heap，其实就是用 malloc()&nbsp;或&nbsp;默认的 new 操作符在 Process Heap 里一小块一小块地割肉 ^_^）</li><li><strong style="font-size: 12pt;">栈</strong>（Stack，内存由调用者或被调用者自动管理）</li></ul></li></ul><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　资源下载地址：</span><a href="http://ldcsaa.googlecode.com/files/socket_server_and_client.zip" style="color: #009933; text-decoration: initial;"><span style="font-size: 12pt;">http://ldcsaa.googlecode.com/files/socket_server_and_client.zip</span></a><span style="font-size: 12pt;">&nbsp;（源代码在 Common/Src 目录中）</span></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;">&nbsp;</p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><strong style="font-size: 12pt;">4、《<a href="http://www.cnblogs.com/ldcsaa/archive/2012/02/13/2348588.html" style="color: #009933; text-decoration: initial;">实现 Win32 程序的消息映射宏（类似 MFC ）</a>》</strong></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　摘要：对于消息映射宏，不用多说了，用过 MFC 的人都很清楚。但目前有不少程序由于各种原因并没有使用 MFC，所以本帖讨论一下如何在 Win32 程序中实现类似MFC的消息映射宏。其实 Windows 的头文件 &#8220;WindowsX.h&#8221;（注意：不是&#8220;Windows.h&#8221;） 中提供了一些有用的宏来帮助我们实现消息映射。本座是也基于这个头文件实现消息映射。</span></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　资源下载地址：</span><a href="http://ldcsaa.googlecode.com/files/socket_server_and_client.zip" style="color: #009933; text-decoration: initial;"><span style="font-size: 12pt;">http://ldcsaa.googlecode.com/files/socket_server_and_client.zip</span></a><span style="font-size: 12pt;">&nbsp;（源代码在 Common/Src/Win32Helper.h 文件中）</span></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;">&nbsp;</p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><strong style="font-size: 12pt;">5、《<a href="http://www.cnblogs.com/ldcsaa/archive/2012/02/12/2348398.html" style="color: #009933; text-decoration: initial;">用宏实现 C++ Singleton 模式</a>》</strong></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　摘要：Singleton 设计模式应用非常广泛，实现起来也很简单，无非是私有化若干个构造函数，&#8220;operator =&#8221; 操作符，以及提供一个静态的创建和销毁方法。但是对每个类都写这些雷同的代码是本座不能容忍的，因此，本座使用宏把整个 Singleton 模式封装起来，无论是类的定义还是类的使用的极其简单。</span></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　资源下载地址：</span><a href="http://ldcsaa.googlecode.com/files/socket_server_and_client.zip" style="color: #009933; text-decoration: initial;"><span style="font-size: 12pt;">http://ldcsaa.googlecode.com/files/socket_server_and_client.zip</span></a><span style="font-size: 12pt;">&nbsp;（源代码在 Common/Src/Singleton.h 文件中）</span></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;">&nbsp;</p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><strong style="font-size: 12pt;">6、《<a href="http://www.cnblogs.com/ldcsaa/archive/2012/02/12/2348302.html" style="color: #009933; text-decoration: initial;">C++ 封装私有堆（Private Heap）</a>》</strong></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　摘要：Private Heap 是 Windows 提供的一种内存内存机制，对于那些需要频繁分配和释放动态内存的应用程序来说，Private Heap 是提高应用程序性能的一大法宝，使用它能降低 new / malloc 的调用排队竞争以及内存空洞。</span></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　资源下载地址：</span><a href="http://ldcsaa.googlecode.com/files/socket_server_and_client.zip" style="color: #009933; text-decoration: initial;"><span style="font-size: 12pt;">http://ldcsaa.googlecode.com/files/socket_server_and_client.zip</span></a><span style="font-size: 12pt;">&nbsp;（源代码在 Common/Src/PrivateHeap.h 文件中）</span></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;">&nbsp;</p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><strong style="font-size: 12pt;">7、《<a href="http://www.cnblogs.com/ldcsaa/archive/2012/02/12/2348160.html" style="color: #009933; text-decoration: initial;">基于 crt debug 实现的 Windows 程序内存泄漏检测工具</a>》</strong></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　摘要：Windows 程序内存泄漏检测是一项十分重要的工作，基于 GUI 的应用程序通常在调试结束时也有内存泄漏报告，但这个报告的信息不全面，不能定位到产生泄漏的具体行号。其实自己实现一个内存泄漏检测工具是一件非常简单的事情，但看过网上写的很多例子，普遍存在两种问题：</span></p><ul style="font-family: Verdana, ����; line-height: normal; background-color: #eeeeee;"><li style="list-style-type: none;"><ul><li><span style="font-size: 12pt;">要么考虑不周全，一种环境下能用，而在另外一种环境下却不能很好工作，或者漏洞报告的输出方式不合理。</span></li><li><span style="font-size: 12pt;">要么过于保守，例如：完全没有必要在 _malloc_dbg() 和 _free_dbg() 的调用前后用 CriticalSection 进行保护（跟踪一下多线程环境下 new 和 malloc 的代码就会明白）。</span></li></ul></li></ul><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　资源下载地址：</span><a href="http://ldcsaa.googlecode.com/files/socket_server_and_client.zip" style="color: #009933; text-decoration: initial;"><span style="font-size: 12pt;">http://ldcsaa.googlecode.com/files/socket_server_and_client.zip</span></a><span style="font-size: 12pt;">&nbsp;（源代码在 Common/Src/debug/win32_crtdbg.h 文件中）</span></p><hr style="font-family: Verdana, ����; line-height: normal; background-color: #eeeeee;" /><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 18pt;"><strong>Java</strong></span></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><strong style="font-size: 12pt;">1、《<a href="http://www.cnblogs.com/ldcsaa/archive/2012/12/25/2831662.html" style="color: #009933; text-decoration: initial;">Portal-Basic Java Web 应用开发框架 v3.0.1 正式发布（源码、示例及文档）</a>》</strong></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　摘要：Portal-Basic Java Web应用开发框架（简称 Portal-Basic）是一套功能完备的高性能Full-Stack Web应用开发框架，内置稳定高效的MVC基础架构和DAO框架（已内置Hibernate、MyBatis和JDBC支持），集成 Action拦截、Form Bean / Dao Bean / Spring Bean装配、国际化、文件上传下载和缓存等基础Web应用组件，提供高度灵活的纯 Jsp/Servlet API 编程模型，完美整合 Spring，支持Action Convention&#8220;零配置&#8221;，能快速开发传统风格和RESTful风格的Web应用程序，文档和代码清晰完善，非常容易学习。</span></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　资源下载地址：</span><a href="http://code.google.com/p/portal-basic/downloads/list" style="color: #009933; text-decoration: initial;"><span style="font-size: 12pt;">http://code.google.com/p/portal-basic/downloads/list</span></a></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;">&nbsp;</p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><strong style="font-size: 12pt;">2、《<a href="http://www.cnblogs.com/ldcsaa/archive/2012/06/25/2560481.html" style="color: #009933; text-decoration: initial;">用 Java 实现的日志切割清理工具（源代码下载）</a>》</strong></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　摘要：对于服务器的日常维护来说，日志清理是非常重要的事情，如果残留日志过多则严重浪费磁盘空间同时影响服务的性能。如果用手工方式进行清理，会花费太多时间，并且很多时候难以满足实际要求。例如：如何在每个星期六凌晨3点把超过2G大的日志文件进行切割，保留最新的100M日志记录？网上没有发现能满足本座要求的日志切割工具，因此花了一些闲暇时间自己写了一个。由于要在多个平台上使用，为了方便采用 Java 实现。本工具命名为&nbsp;</span><strong style="font-size: 12pt;">LogCutter</strong>，主要有以下特点：</p><ul style="font-family: Verdana, ����; line-height: normal; background-color: #eeeeee;"><li style="list-style-type: none;"><ul><li><span style="font-size: 12pt;">支持 Linux、Mac 和 Windows 等所有常见操作系统平台</span></li><li><span style="font-size: 12pt;">支持命令行交互式运行</span></li><li><span style="font-size: 12pt;">支持后台非交互式运行（Linux/MAC 下使用 daemon 进程实现，Windows 用系统 Service 实现）</span></li><li><span style="font-size: 12pt;">支持两种日志清理方式（删除日志文件或切割日志文件）</span></li><li><span style="font-size: 12pt;">支持对 GB18030、UTF-8、UTF-16LE、UTF-16BE 等常用日志文件类型进行切割（不会发生切掉半个字符的情况）</span></li><li><span style="font-size: 12pt;">高度可配置（程序执行周期、要删除的日志文件过期时间、要切割的日志文件阀值和保留大小等均可配置</span></li></ul></li></ul><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　资源下载地址：</span><a href="http://ldcsaa.googlecode.com/files/LogCutter.zip" style="color: #009933; text-decoration: initial;"><span style="font-size: 12pt;">http://ldcsaa.googlecode.com/files/LogCutter.zip</span></a></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;">&nbsp;</p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><strong style="font-size: 12pt;">3、《<a href="http://www.cnblogs.com/ldcsaa/archive/2012/02/23/2364036.html" style="color: #009933; text-decoration: initial;">通用 Java 文件上传和下载组件的设计与实现</a>》</strong></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　摘要：文件上传和下载是 Web 应用中的一个常见功能，相信各位或多或少都曾写过这方面相关的代码。但本座看过不少人在实现上传或下载功能时总是不知不觉间与程序的业务逻辑纠缠在一起，因此，当其他地方要用到这些功能时则无可避免地 Copy / Pase，然后再进行修改。这样丑陋不堪的做法导致非常容易出错不说，更大的问题是严重浪费时间不断做重复类似的工作，这是本座绝不能容忍的。哎，人生苦短啊，浪费时间在这些重复工作身上实在是不值得，何不把这些时间省出来打几盘罗马或者踢一场球？为此，本座利用一些闲暇之时光编写了一个通用的文件上传和文件下载组件，实现方法纯粹是基于 JSP，没有太高的技术难度，总之老少咸宜 ^_^。现把设计的思路和实现的方法向各位娓娓道来，希望能起到抛砖引玉的效果，激发大家的创造性思维。</span></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　资源下载地址：</span><a href="http://code.google.com/p/portal-basic/downloads/list" style="color: #009933; text-decoration: initial;"><span style="font-size: 12pt;">http://code.google.com/p/portal-basic/downloads/list</span></a><span style="font-size: 12pt;">&nbsp;（作为 Portal-Basic 第一部分，代码在 com.bruce.util.http 包中）</span></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;">&nbsp;</p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><strong style="font-size: 12pt;">4、《<a href="http://www.cnblogs.com/ldcsaa/archive/2012/02/16/2353030.html" style="color: #009933; text-decoration: initial;">深度剖析：Java POJO Bean 对象与 Web Form 表单的自动装配</a>》</strong></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　摘要：时下很多 Web 框架 都实现了 Form 表单域与 Java 对象属性的自动装配功能，该功能确实非常有用，试想如果没这功能则势必到处冲积着 request.getParameter() 系列方法与类型转换方法的调用。重复代码量大，容易出错，同时又不美观，影响市容。现在的问题是，这些框架通过什么方法实现自动装配的？如果不用这些框架我们自己如何去实现呢？尤其对于那些纯 JSP/Servlet 应用，要是拥有自动装配功能该多好啊！本座深知各位之期盼，决定把自动装配的原理和实现方法娓娓道来。</span></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　资源下载地址：</span><a href="http://code.google.com/p/portal-basic/downloads/list" style="color: #009933; text-decoration: initial;"><span style="font-size: 12pt;">http://code.google.com/p/portal-basic/downloads/list</span></a><span style="font-size: 12pt;">&nbsp;（作为 Portal-Basic 第一部分，代码在 com.bruce.util 包中）</span></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;">&nbsp;</p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><strong style="font-size: 12pt;">5、《<a href="http://www.cnblogs.com/ldcsaa/archive/2012/02/14/2350751.html" style="color: #009933; text-decoration: initial;">Linux 安装 MySQL / MySQL 主从备份</a>》</strong></p><p style="margin: 10px 0px; font-family: Verdana, ����; background-color: #eeeeee;"><span style="font-size: 12pt;">　　资源下载地址：</span><a href="http://ldcsaa.googlecode.com/files/services.zip" style="color: #009933; text-decoration: initial;"><span style="font-size: 12pt;">http://ldcsaa.googlecode.com/files/services.zip</span><br /><br /><span style="font-size: 12pt;">本文</span></a><span style="font-size: 12pt;">转自：</span><span style="font-size: 12pt;">http://www.cppblog.com/ldcsaa/archive/2013/01/07/197048.html</span></p><img src ="http://www.cppblog.com/wanghaiguang/aggbug/197059.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2013-01-07 10:39 <a href="http://www.cppblog.com/wanghaiguang/archive/2013/01/07/197059.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>锁定一个View视图的大小，禁止用户拖拉边框来进行放大或缩小界面大小</title><link>http://www.cppblog.com/wanghaiguang/archive/2013/01/05/196972.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Sat, 05 Jan 2013 07:06:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2013/01/05/196972.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/196972.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2013/01/05/196972.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/196972.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/196972.html</trackback:ping><description><![CDATA[<span style="color: #333333; font-family: Verdana; line-height: 24px; background-color: #f5f5f5; font-size: 12pt;">重载框架的PreCreateWindow函数</span><br style="color: #333333; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #f5f5f5;" /><br style="color: #333333; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #f5f5f5;" /><span style="color: #333333; font-family: Verdana; line-height: 24px; background-color: #f5f5f5; font-size: 12pt;">CMainFrame::PreCreateWindow(CREATESTRUCT&nbsp;&amp;cs)</span><br style="color: #333333; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #f5f5f5;" /><span style="color: #333333; font-family: Verdana; line-height: 24px; background-color: #f5f5f5; font-size: 12pt;">{</span><br style="color: #333333; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #f5f5f5;" /><span style="color: #333333; font-family: Verdana; line-height: 24px; background-color: #f5f5f5; font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cs.style&amp;=~WS_THICKFRAME;</span><br style="color: #333333; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #f5f5f5;" /><span style="color: #333333; font-family: Verdana; line-height: 24px; background-color: #f5f5f5; font-size: 12pt;">}</span><img src ="http://www.cppblog.com/wanghaiguang/aggbug/196972.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2013-01-05 15:06 <a href="http://www.cppblog.com/wanghaiguang/archive/2013/01/05/196972.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]Win32应用程序中进程间通信方法分析与比较</title><link>http://www.cppblog.com/wanghaiguang/archive/2012/11/20/195414.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Tue, 20 Nov 2012 08:47:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2012/11/20/195414.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/195414.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2012/11/20/195414.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/195414.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/195414.html</trackback:ping><description><![CDATA[<p align="center" style="line-height: 19px; margin-top: 10px; margin-bottom: 10px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff;"><strong style="font-family: Verdana;">Win32</strong><strong>应用程序中进程间通信方法分析与比较</strong></p><p align="center" style="line-height: 19px; margin-top: 10px; margin-bottom: 10px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff;"><span style="font-family: Verdana;">来源:Intetnet</span><br /></p><p style="line-height: 19px; margin-top: 10px; margin-bottom: 10px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff;">&nbsp;</p><p style="line-height: 19px; margin-top: 10px; margin-bottom: 10px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff;"><strong style="font-family: Verdana;"></strong></p><p style="margin-top:7.5pt;margin-right:0cm;margin-bottom:7.5pt;margin-left: 0cm;line-height:200%;background:white"><strong><span style="font-size: 10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;;color:#4B4B4B">1&nbsp;</span></strong><strong><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">进程与进程通信</span></strong></p>  <p style="margin: 7.5pt 0cm; line-height: 200%; background-color: white; background-position: initial initial; background-repeat: initial initial;"><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　进程是装入内存并准备执行的程序，每个进程都有私有的虚拟地址空间，由代码、数据以及它可利用的系统资源</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">如文件、管道等</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">组成。多进程</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">/</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">多线程是</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Windows</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">操作系统的一个基本特征。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Microsoft Win32</span><span style="font-size:10.0pt;line-height: 200%;color:#4B4B4B">应用编程接口</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(Application Programming Interface, API)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">提供了大量支持应用程序间数据共享和交换的机制，这些机制行使的活动称为进程间通信</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(InterProcess Communication, IPC)</span><span style="font-size: 10.0pt;line-height:200%;color:#4B4B4B">，进程通信就是指不同进程间进行数据共享和数据交换。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　正因为使用</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Win32 API</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">进行进程通信方式有多种，如何选择恰当的通信方式就成为应用开发中的一个重要问题，下面本文将对</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Win32</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">中进程通信的几种方法加以分析和比较。</span></p>  <p style="margin: 7.5pt 0cm; line-height: 200%; background-color: white; background-position: initial initial; background-repeat: initial initial;"><strong><span style="font-size:10.0pt;line-height:200%;font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;color:#4B4B4B">2&nbsp;</span></strong><strong><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">进程通信方法</span></strong></p>  <p style="margin: 7.5pt 0cm; line-height: 200%; background-color: white; background-position: initial initial; background-repeat: initial initial;"><strong><span style="font-size:10.0pt;line-height:200%;font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;color:#4B4B4B">2.1&nbsp;</span></strong><strong><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">文件映射</span></strong><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　文件映射</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(Memory-Mapped Files)</span><span style="font-size:10.0pt; line-height:200%; color:#4B4B4B">能使进程把文件内容当作进程地址区间一块内存那样来对待。因此，进程不必使用文件</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">I/O</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">操作，只需简单的指针操作就可读取和修改文件的内容。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Win32 API</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">允许多个进程访问同一文件映射对象，各个进程在它自己的地址空间里接收内存的指针。通过使用这些指针，不同进程就可以读或修改文件的内容，实现了对文件中数据的共享。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　应用程序有三种方法来使多个进程共享一个文件映射对象。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(1)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">继承：第一个进程建立文件映射对象，它的子进程继承该对象的句柄。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(2)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">命名文件映射：第一个进程在建立文件映射对象时可以给该对象指定一个名字</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">可与文件名不同</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">。第二个进程可通过这个名字打开此文件映射对象。另外，第一个进程也可以通过一些其它</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">IPC</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">机制</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">有名管道、邮件槽等</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">把名字传给第二个进程。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(3)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">句柄复制：第一个进程建立文件映射对象，然后通过其它</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">IPC</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">机制</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">有名管道、邮件槽等</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">把对象句柄传递给第二个进程。第二个进程复制该句柄就取得对该文件映射对象的访问权限。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　文件映射是在多个进程间共享数据的非常有效方法，有较好的安全性。但文件映射只能用于本地机器的进程之间，不能用于网络中，而开发者还必须控制进程间的同步。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> <strong>2.2&nbsp;</strong></span><strong><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">共享内存</span></strong><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Win32 API</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">中共享内存</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(Shared Memory)</span><span style="font-size:10.0pt;line-height: 200%;color:#4B4B4B">实际就是文件映射的一种特殊情况。进程在创建文件映射对象时用</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">0xFFFFFFFF</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">来代替文件句柄</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(HANDLE)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">，就表示了对应的文件映射对象是从操作系统页面文件访问内存，其它进程打开该文件映射对象就可以访问该内存块。由于共享内存是用文件映射实现的，所以它也有较好的安全性，也只能运行于同一计算机上的进程之间。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> <strong>2.3&nbsp;</strong></span><strong><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">匿名管道</span></strong><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　管道</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(Pipe)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">是一种具有两个端点的通信通道：有一端句柄的进程可以和有另一端句柄的进程通信。管道可以是单向－一端是只读的，另一端点是只写的；也可以是双向的一管道的两端点既可读也可写。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　匿名管道</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(Anonymous Pipe)</span><span style="font-size:10.0pt;line-height: 200%;color:#4B4B4B">是在父进程和子进程之间，或同一父进程的两个子进程之间传输数据的无名字的单向管道。通常由父进程创建管道，然后由要通信的子进程继承通道的读端点句柄或写端点句柄，然后实现通信。父进程还可以建立两个或更多个继承匿名管道读和写句柄的子进程。这些子进程可以使用管道直接通信，不需要通过父进程。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　匿名管道是单机上实现子进程标准</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">I/O</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">重定向的有效方法，它不能在网上使用，也不能用于两个不相关的进程之间。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> <strong>2.4&nbsp;</strong></span><strong><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">命名管道</span></strong><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　命名管道</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(Named Pipe)</span><span style="font-size:10.0pt;line-height: 200%;color:#4B4B4B">是服务器进程和一个或多个客户进程之间通信的单向或双向管道。不同于匿名管道的是命名管道可以在不相关的进程之间和不同计算机之间使用，服务器建立命名管道时给它指定一个名字，任何进程都可以通过该名字打开管道的另一端，根据给定的权限和服务器进程通信。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　命名管道提供了相对简单的编程接口，使通过网络传输数据并不比同一计算机上两进程之间通信更困难，不过如果要同时和多个进程通信它就力不从心了。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> <strong>2.5&nbsp;</strong></span><strong><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">邮件槽</span></strong><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　邮件槽</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(Mailslots)</span><span style="font-size:10.0pt;line-height: 200%;color:#4B4B4B">提供进程间单向通信能力，任何进程都能建立邮件槽成为邮件槽服务器。其它进程，称为邮件槽客户，可以通过邮件槽的名字给邮件槽服务器进程发送消息。进来的消息一直放在邮件槽中，直到服务器进程读取它为止。一个进程既可以是邮件槽服务器也可以是邮件槽客户，因此可建立多个邮件槽实现进程间的双向通信。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　通过邮件槽可以给本地计算机上的邮件槽、其它计算机上的邮件槽或指定网络区域中所有计算机上有同样名字的邮件槽发送消息。广播通信的消息长度不能超过</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">400</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">字节，非广播消息的长度则受邮件槽服务器指定的最大消息长度的限制。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　邮件槽与命名管道相似，不过它传输数据是通过不可靠的数据报</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">如</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">TCP/IP</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">协议中的</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">UDP</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">包</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">完成的，一旦网络发生错误则无法保证消息正确地接收，而命名管道传输数据则是建立在可靠连接基础上的。不过邮件槽有简化的编程接口和给指定网络区域内的所有计算机广播消息的能力，所以邮件槽不失为应用程序发送和接收消息的另一种选择。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> <strong>2.6&nbsp;</strong></span><strong><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">剪贴板</span></strong><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　剪贴板</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(Clipped Board)</span><span style="font-size:10.0pt;line-height: 200%;color:#4B4B4B">实质是</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Win32 API</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">中一组用来传输数据的函数和消息，为</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Windows</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">应用程序之间进行数据共享提供了一个中介，</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Windows</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">已建立的剪切</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">复制</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">－粘贴的机制为不同应用程序之间共享不同格式数据提供了一条捷径。当用户在应用程序中执行剪切或复制操作时，应用程序把选取的数据用一种或多种格式放在剪贴板上。然后任何其它应用程序都可以从剪贴板上拾取数据，从给定格式中选择适合自己的格式。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　剪贴板是一个非常松散的交换媒介，可以支持任何数据格式，每一格式由一无符号整数标识，对标准</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">预定义</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">剪贴板格式，该值是</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Win32 API</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">定义的常量；对非标准格式可以使用</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Register Clipboard Format</span><span style="font-size:10.0pt; line-height:200%; color:#4B4B4B">函数注册为新的剪贴板格式。利用剪贴板进行交换的数据只需在数据格式上一致或都可以转化为某种格式就行。但剪贴板只能在基于</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Windows</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">的程序中使用，不能在网络上使用。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> <strong>2.7&nbsp;</strong></span><strong><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">动态数据交换</span></strong><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　动态数据交换</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(DDE)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">是使用共享内存在应用程序之间进行数据交换的一种进程间通信形式。应用程序可以使用</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">DDE</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">进行一次性数据传输，也可以当出现新数据时，通过发送更新值在应用程序间动态交换数据。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">DDE</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">和剪贴板一样既支持标准数据格式</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">如文本、位图等</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">，又可以支持自己定义的数据格式。但它们的数据传输机制却不同，一个明显区别是剪贴板操作几乎总是用作对用户指定操作的一次性应答－如从菜单中选择</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Paste</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">命令。尽管</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">DDE</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">也可以由用户启动，但它继续发挥作用一般不必用户进一步干预。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">DDE</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">有三种数据交换方式：</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(1) </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">冷链：数据交换是一次性数据传输，与剪贴板相同。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(2) </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">温链：当数据交换时服务器通知客户，然后客户必须请求新的数据。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(3) </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">热链：当数据交换时服务器自动给客户发送数据。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">DDE</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">交换可以发生在单机或网络中不同计算机的应用程序之间。开发者还可以定义定制的</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">DDE</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">数据格式进行应用程序之间特别目的</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">IPC</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">，它们有更紧密耦合的通信要求。大多数基于</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Windows</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">的应用程序都支持</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">DDE</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> <strong>2.8&nbsp;</strong></span><strong><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">对象连接与嵌入</span></strong><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　应用程序利用对象连接与嵌入</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(OLE)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">技术管理复合文档</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">由多种数据格式组成的文档</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">，</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">OLE</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">提供使某应用程序更容易调用其它应用程序进行数据编辑的服务。例如，</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">OLE</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">支持的字处理器可以嵌套电子表格，当用户要编辑电子表格时</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">OLE</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">库可自动启动电子表格编辑器。当用户退出电子表格编辑器时，该表格已在原始字处理器文档中得到更新。在这里电子表格编辑器变成了字处理器的扩展，而如果使用</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">DDE</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">，用户要显式地启动电子表格编辑器。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　同</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">DDE</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">技术相同，大多数基于</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Windows</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">的应用程序都支持</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">OLE</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">技术。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> <strong>2.9&nbsp;</strong></span><strong><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">动态连接库</span></strong><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Win32</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">动态连接库</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(DLL)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">中的全局数据可以被调用</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">DLL</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">的所有进程共享，这就又给进程间通信开辟了一条新的途径，当然访问时要注意同步问题。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　虽然可以通过</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">DLL</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">进行进程间数据共享，但从数据安全的角度考虑，我们并不提倡这种方法，使用带有访问权限控制的共享内存的方法更好一些。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> <strong>2.10&nbsp;</strong></span><strong><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">远程过程调用</span></strong><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Win32 API</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">提供的远程过程调用</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(RPC)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">使应用程序可以使用远程调用函数，这使在网络上用</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">RPC</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">进行进程通信就像函数调用那样简单。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">RPC</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">既可以在单机不同进程间使用也可以在网络中使用。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　由于</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Win32 API</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">提供的</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">RPC</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">服从</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">OSF-DCE(Open Software Foundation Distributed Computing Environment)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">标准。所以通过</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Win32 API</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">编写的</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">RPC</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">应用程序能与其它操作系统上支持</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">DEC</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">的</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">RPC</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">应用程序通信。使用</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">RPC</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">开发者可以建立高性能、紧密耦合的分布式应用程序。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> <strong>2.11 NetBios</strong></span><strong><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">函数</span></strong><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Win32 API</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">提供</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">NetBios</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">函数用于处理低级网络控制，这主要是为</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">IBM NetBios</span><span style="font-size:10.0pt;line-height: 200%;color:#4B4B4B">系统编写与</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Windows</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">的接口。除非那些有特殊低级网络功能要求的应用程序，其它应用程序最好不要使用</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">NetBios</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">函数来进行进程间通信。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> <strong>2.12 Sockets</strong><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Windows Sockets</span><span style="font-size:10.0pt;line-height: 200%;color:#4B4B4B">规范是以</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">U.C.Berkeley</span><span style="font-size:10.0pt;line-height: 200%;color:#4B4B4B">大学</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">BSD UNIX</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">中流行的</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Socket</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">接口为范例定义的一套</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Windows</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">下的网络编程接口。除了</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Berkeley Socket</span><span style="font-size:10.0pt;line-height: 200%;color:#4B4B4B">原有的库函数以外，还扩展了一组针对</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Windows</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">的函数，使程序员可以充分利用</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Windows</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">的消息机制进行编程。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　现在通过</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Sockets</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">实现进程通信的网络应用越来越多，这主要的原因是</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Sockets</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">的跨平台性要比其它</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">IPC</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">机制好得多，另外</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">WinSock 2.0</span><span style="font-size:10.0pt;line-height: 200%;color:#4B4B4B">不仅支持</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">TCP/IP</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">协议，而且还支持其它协议</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">(</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">如</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">IPX)</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Sockets</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">的唯一缺点是它支持的是底层通信操作，这使得在单机的进程间进行简单数据传递不太方便，这时使用下面将介绍的</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">WM_COPYDATA</span><span style="font-size:10.0pt;line-height: 200%;color:#4B4B4B">消息将更合适些。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> <strong>2.13 WM_COPYDATA</strong></span><strong><span style="font-size:10.0pt;line-height: 200%;color:#4B4B4B">消息</span></strong><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">WM_COPYDATA</span><span style="font-size:10.0pt;line-height: 200%;color:#4B4B4B">是一种非常强大却鲜为人知的消息。当一个应用向另一个应用传送数据时，发送方只需使用调用</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">SendMessage</span><span style="font-size:10.0pt;line-height: 200%;color:#4B4B4B">函数，参数是目的窗口的句柄、传递数据的起始地址、</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">WM_COPYDATA</span><span style="font-size:10.0pt;line-height: 200%;color:#4B4B4B">消息。接收方只需像处理其它消息那样处理</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">WM_COPY DATA</span><span style="font-size:10.0pt;line-height: 200%;color:#4B4B4B">消息，这样收发双方就实现了数据共享。</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B"><br /> </span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">WM_COPYDATA</span><span style="font-size:10.0pt;line-height: 200%;color:#4B4B4B">是一种非常简单的方法，它在底层实际上是通过文件映射来实现的。它的缺点是灵活性不高，并且它只能用于</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Windows</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">平台的单机环境下。</span></p>  <p style="margin: 7.5pt 0cm; line-height: 200%; background-color: white; background-position: initial initial; background-repeat: initial initial;"><strong><span style="font-size:10.0pt;line-height:200%;font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;color:#4B4B4B">3&nbsp;</span></strong><strong><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">结束语</span></strong></p>  <p style="margin: 7.5pt 0cm; line-height: 200%; background-color: white; background-position: initial initial; background-repeat: initial initial;"><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">　　</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">Win32 API</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">为应用程序实现进程间通信提供了如此多种选择方案，那么开发者如何进行选择呢？通常在决定使用哪种</span><span style="font-size:10.0pt;line-height:200%;font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;; color:#4B4B4B">IPC</span><span style="font-size:10.0pt;line-height:200%;color:#4B4B4B">方法之前应考虑下一些问题，如应用程序是在网络环境下还是在单机环境下工作等。</span></p><p style="line-height: 19px; margin-top: 10px; margin-bottom: 10px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff;"><span style="font-family: Verdana;"><br />本文转自：</span>http://www.cnblogs.com/erwin/archive/2007/04/16/715084.html</p><img src ="http://www.cppblog.com/wanghaiguang/aggbug/195414.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2012-11-20 16:47 <a href="http://www.cppblog.com/wanghaiguang/archive/2012/11/20/195414.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++高效编程忠告（转载）</title><link>http://www.cppblog.com/wanghaiguang/archive/2012/10/25/193840.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Thu, 25 Oct 2012 07:20:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2012/10/25/193840.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/193840.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2012/10/25/193840.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/193840.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/193840.html</trackback:ping><description><![CDATA[<span style="font-family: Lucida Console">这是对C++高效编程的一个总结, 很有指导作用.</span><br /><br /><strong><span style="font-family: Lucida Console; color: red">一、#include &#8220;filename.h&#8221;和#include &lt;filename.h&gt;的区别</span></strong><br /><span style="font-family: Lucida Console">#include &#8220;filename.h&#8221;是指编译器将从当前工作目录上开始查找此文件</span><br /><span style="font-family: Lucida Console">#include &lt;filename.h&gt;是指编译器将从标准库目录中开始查找此文件</span><br /><br /><strong><span style="font-family: Lucida Console; color: red">二、头文件的作用</span></strong><br /><span style="font-family: Lucida Console">加强安全检测</span><br /><span style="font-family: Lucida Console">通过头文件可能方便地调用库功能，而不必关心其实现方式</span><br /><br /><strong><span style="font-family: Lucida Console; color: red">三、* , &amp;修饰符的位置<br /></span></strong><span style="font-family: Lucida Console">int *i,j; // better for read</span><br /><span style="font-family: Lucida Console">&nbsp;i = new int(0);</span><br /><span style="font-family: Lucida Console">&nbsp;j = 0;</span><br /><span style="font-family: Lucida Console">&nbsp;int *&amp;y = i; // pointer's reference</span><br /><span style="font-family: Lucida Console">对于*和&amp;修饰符，为了避免误解，最好将修饰符紧靠变量名</span><br /><br /><strong><span style="font-family: Lucida Console; color: red">四、if语句</span></strong><br /><span style="font-family: Lucida Console">不要将布尔变量与任何值进行比较，那会很容易出错的。</span><br /><span style="font-family: Lucida Console">整形变量必须要有类型相同的值进行比较</span><br /><span style="font-family: Lucida Console">浮点变量最好少比相等，可以通过求差与较小的数比较</span><br /><span style="font-family: Lucida Console">指针变量要和NULL进行比较，不要和布尔型和整形比较</span><br /><br /><strong><span style="font-family: Lucida Console; color: red">五、const和#define的比较</span></strong><br /><span style="font-family: Lucida Console">const有数据类型，#define没有数据类型</span><br /><span style="font-family: Lucida Console">个别编译器中const可以进行调试，#define不可以进行调试</span><br /><span style="font-family: Lucida Console">在类中定义常量有两种方式</span><br /><span style="font-family: Lucida Console">1、 在类在声明常量，但不赋值，在构造函数初始化表中进行赋值；（常量和引用类型的成员变量必须通过初始化列表来初始化赋值）</span><br /><span style="font-family: Lucida Console">2、 用枚举代替const常量。</span><br /><br /><strong><span style="font-family: Lucida Console; color: red">六、C++函数中值的传递方式</span></strong><br /><span style="font-family: Lucida Console">有三种方式：值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference)</span><br /><span style="font-family: Lucida Console">void fun(char c) //pass by value</span><br /><span style="font-family: Lucida Console">void fun(char *str) //pass by pointer</span><br /><span style="font-family: Lucida Console">void fun(char &amp;str) //pass by reference</span><br /><span style="font-family: Lucida Console">如果输入参数是以值传递的话，最好使用引用传递代替，因为引用传递省去了临时对象的构造和析构</span><br /><span style="font-family: Lucida Console">函数的返回类型不能省略，就算没有也要加个void</span><br /><br /><strong><span style="font-family: Lucida Console; color: red">七、函数体中的指针或引用常量不能被返回</span></strong> 
<div class="code"><span style="font-family: Lucida Console">Char *func(void)</span><br /><span style="font-family: Lucida Console">{</span><br /><span style="font-family: Lucida Console">&nbsp;char str[]=&#8221;Hello Word&#8221;;</span><br /><span style="font-family: Lucida Console">&nbsp;//这个是不能被返回的，因为str是个指定变量，不是一般的值，函数结束后会被注销掉</span><br /><span style="font-family: Lucida Console">&nbsp;return str; </span><br /><span style="font-family: Lucida Console">}</span></div><span style="font-family: Lucida Console">函数体内的指针变量并不会随着函数的消亡而自动释放</span><br /><br /><strong><span style="font-family: Lucida Console; color: red">八、一个内存拷贝函数的实现体</span></strong> 
<div class="code"><span style="font-family: Lucida Console">void *memcpy(void *pvTo,const void *pvFrom,size_t size)</span><br /><br /><span style="font-family: Lucida Console">{</span><br /><br /><span style="font-family: Lucida Console">&nbsp;assert((pvTo!=NULL)&amp;&amp;(pvFrom!=NULL));</span><br /><br /><span style="font-family: Lucida Console">&nbsp;byte *pbTo=(byte*)pvTo; //防止地址被改变</span><br /><br /><span style="font-family: Lucida Console">&nbsp;byte *pbFrom=(byte*)pvFrom;</span><br /><br /><span style="font-family: Lucida Console">&nbsp;while (size-- &gt;0)</span><br /><br /><span style="font-family: Lucida Console">&nbsp;pbTo++ = pbForm++;</span><br /><br /><span style="font-family: Lucida Console">&nbsp;return pvTo;</span><br /><br /><span style="font-family: Lucida Console">} </span><br /></div><br /><strong><span style="font-family: Lucida Console; color: red">九、内存的分配方式</span></strong><br /><span style="font-family: Lucida Console">分配方式有三种，请记住，说不定那天去面试的时候就会有人问你这问题</span><br /><span style="font-family: Lucida Console">1、 静态存储区，是在程序编译时就已经分配好的，在整个运行期间都存在，如全局变量、常量。（程序编译后运行时包含code和data两部分，其中data即为静态存储区分配，程序一开始运行便分配整个data的东东）</span><br /><span style="font-family: Lucida Console">2、 栈上分配，函数内的局部变量就是从这分配的，但分配的内存容易有限。</span><br /><span style="font-family: Lucida Console">3、 堆上分配，也称动态分配，如我们用new,malloc分配内存，用delete,free来释放的内存。</span><br /><br /><strong><span style="font-family: Lucida Console; color: red">十、内存分配的注意事项</span></strong><br /><span style="font-family: Lucida Console">用new或malloc分配内存时，必须要对此指针赋初值。</span><br /><span style="font-family: Lucida Console">用delete 或free释放内存后，必须要将指针指向NULL</span><br /><span style="font-family: Lucida Console">不能修改指向常量的指针数据</span><br /><br /><strong><span style="font-family: Lucida Console; color: red">十一、内容复制与比较</span></strong> 
<div class="code"><span style="font-family: Lucida Console">//数组&#8230;&#8230;</span><br /><span style="font-family: Lucida Console">char a[]=&#8221;Hello Word!&#8221;;</span><br /><span style="font-family: Lucida Console">char b[10];</span><br /><span style="font-family: Lucida Console">strcpy(b,a);</span><br /><span style="font-family: Lucida Console">if (strcmp(a,b)==0)</span><br /><span style="font-family: Lucida Console">{}</span></div>
<div class="code"><span style="font-family: Lucida Console">//指针&#8230;&#8230;</span><br /><span style="font-family: Lucida Console">char a[]=&#8221;Hello Word!&#8221;;</span><br /><span style="font-family: Lucida Console">char *p;</span><br /><span style="font-family: Lucida Console">p=new char[strlen(a)+1];</span><br /><span style="font-family: Lucida Console">strcpy(p,a);</span><br /><span style="font-family: Lucida Console">if (strcmp(p,a)==0)</span><br /><span style="font-family: Lucida Console">{}</span></div><br /><strong><span style="font-family: Lucida Console; color: red">十二、sizeof的问题</span></strong><br /><span style="font-family: Lucida Console">记住一点，C++无法知道指针所指对象的大小，指针的大小永远为4字节 </span>
<div class="code"><span style="font-family: Lucida Console">char a[]=&#8221;Hello World!&#8221;</span><br /><span style="font-family: Lucida Console">char *p=a;</span><br /><span style="font-family: Lucida Console">count&lt;&lt;sizeof(a)&lt;&lt;end; //12字节</span><br /><span style="font-family: Lucida Console">count&lt;&lt;sizeof(p)&lt;&lt;endl; //4字节</span></div><span style="font-family: Lucida Console">而且，在函数中，数组参数退化为指针，所以下面的内容永远输出为4 </span>
<div class="code"><span style="font-family: Lucida Console">void fun(char a[1000])</span><br /><span style="font-family: Lucida Console">{</span><br /><span style="font-family: Lucida Console">count&lt;&lt;sizeof(a)&lt;&lt;endl; //输出4而不是1000</span><br /><span style="font-family: Lucida Console">}</span></div><br /><strong><span style="font-family: Lucida Console; color: red">十三、关于指针</span></strong><br /><span style="font-family: Lucida Console">1、 指针创建时必须被初始化</span><br /><span style="font-family: Lucida Console">2、 指针在free 或delete后必须置为NULL</span><br /><span style="font-family: Lucida Console">3、 指针的长度都为4字节</span><br /><span style="font-family: Lucida Console">4、释放内存时，如果是数组指针，必须要释放掉所有的内存，如 </span>
<div class="code"><span style="font-family: Lucida Console">char *p=new char[100];</span><br /><span style="font-family: Lucida Console">strcpy(p,&#8221;Hello World&#8221;);</span><br /><span style="font-family: Lucida Console">delete []p; //注意前面的［］号</span><br /><span style="font-family: Lucida Console">p=NULL;</span></div><span style="font-family: Lucida Console">5、数组指针的内容不能超过数组指针的最大容易。</span><br /><span style="font-family: Lucida Console">如: </span>
<div class="code"><span style="font-family: Lucida Console">char *p=new char[5];</span><br /><span style="font-family: Lucida Console">strcpy(p,&#8221;Hello World&#8221;); //报错 目标容易不够大</span><br /><span style="font-family: Lucida Console">delete []p; //注意前面的［］号</span><br /><span style="font-family: Lucida Console">p=NULL;</span></div><br /><strong><span style="font-family: Lucida Console; color: red">十四、关于malloc/free 和new /delete</span></strong><br /><span style="font-family: Lucida Console">malloc/free 是C/C+的内存分配符，new /delete是C++的内存分配符。</span><br /><span style="font-family: Lucida Console">注意：malloc/free是库函数，new/delete是运算符</span><br /><span style="font-family: Lucida Console">malloc/free不能执行构造函数与析构函数，而new/delete可以</span><br /><span style="font-family: Lucida Console">new/delete不能在C上运行，所以malloc/free不能被淘汰</span><br /><span style="font-family: Lucida Console">两者都必须要成对使用</span><br /><span style="font-family: Lucida Console">C++中可以使用_set_new_hander函数来定义内存分配异常的处理</span><br /><br /><strong><span style="font-family: Lucida Console; color: red">十五、Ｃ++的特性</span></strong><br /><span style="font-family: Lucida Console">Ｃ++新增加有重载(overload)，内联（inline），Const，Virtual四种机制</span><br /><span style="font-family: Lucida Console">重载和内联：即可用于全局函数，也可用于类的成员函数；</span><br /><span style="font-family: Lucida Console">Const和Virtual：只可用于类的成员函数；</span><br /><span style="font-family: Lucida Console">重载：在同一类中，函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数，必须用全局引用符号::引用。</span><br /><span style="font-family: Lucida Console">覆盖是指派生类函数覆盖基类函数：函数名相同；参数相同；基类函数必须有Virtual关键字；不同的范围(派生类和基类)。</span><br /><span style="font-family: Lucida Console">隐藏是指派生类屏蔽了基类的同名函数相同</span><br /><span style="font-family: Lucida Console">1、 函数名相同，但参数不同，此时不论基类有无Virtual关键字，基类函数将被隐藏。</span><br /><span style="font-family: Lucida Console">2、 函数名相同，参数也相同，但基类无Virtual关键字(有就是覆盖)，基类函数将被隐藏。</span><br /><span style="font-family: Lucida Console">内联：inline关键字必须与定义体放在一起，而不是单单放在声明中。</span><br /><span style="font-family: Lucida Console">Const：const是constant的缩写，&#8220;恒定不变&#8221;的意思。被const修饰的东西都受到强制保护，可以预防意外的变动，能提高程序的健壮性。</span><br /><span style="font-family: Lucida Console">1、 参数做输入用的指针型参数，加上const可防止被意外改动。</span><br /><span style="font-family: Lucida Console">2、 按值引用的用户类型做输入参数时，最好将按值传递的改为引用传递，并加上const关键字，目的是为了提高效率。数据类型为内部类型的就没必要做这件事情；如：</span><br /><span style="font-family: Lucida Console">将void Func(A a) 改为void Func(const A &amp;a)。</span><br /><span style="font-family: Lucida Console">而void func(int a)就没必要改成void func(const int &amp;a);</span><br /><span style="font-family: Lucida Console">3、 给返回值为指针类型的函数加上const，会使函数返回值不能被修改，赋给的变量也只能是const型变量。如：函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。</span><br /><span style="font-family: Lucida Console">4、 Const成员函数是指此函数体内只能调用Const成员变量，提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。</span><br /><span style="font-family: Lucida Console">Virtual：虚函数：派生类可以覆盖掉的函数，纯虚函数：只是个空函数，没有函数实现体；</span><br /><br /><strong><span style="font-family: Lucida Console; color: red">十六、extern&#8220;C&#8221;有什么作用？</span></strong><br /><span style="font-family: Lucida Console">Extern &#8220;C&#8221;是由Ｃ＋＋提供的一个连接交换指定符号，用于告诉Ｃ＋＋这段代码是Ｃ函数。这是因为C++编译后库中函数名会变得很长，与C生成的不一致，造成Ｃ＋＋不能直接调用C函数，加上extren &#8220;c&#8221;后，C++就能直接调用C函数了。</span><br /><span style="font-family: Lucida Console">Extern &#8220;C&#8221;主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern &#8220;c&#8221; 关键字即可。</span><br /><br /><strong><span style="font-family: Lucida Console; color: red">十七、构造函数与析构函数</span></strong><br /><span style="font-family: Lucida Console">派生类的构造函数应在初始化表里调用基类的构造函数；</span><br /><span style="font-family: Lucida Console">派生类和基类的析构函数应加Virtual关键字。</span><br /><span style="font-family: Lucida Console">不要小看构造函数和析构函数，其实编起来还是不容易。 </span>
<div class="code"><span style="font-family: Lucida Console">#include &lt;iostream.h&gt;</span><br /><span style="font-family: Lucida Console">class Base</span><br /><span style="font-family: Lucida Console">{</span><br /><span style="font-family: Lucida Console">public: </span><br /><span style="font-family: Lucida Console">virtual ~Base() { cout&lt;&lt; "~Base" &lt;&lt; endl ; }</span><br /><span style="font-family: Lucida Console">};</span><br /><br /><span style="font-family: Lucida Console">class Derived : public Base</span><br /><span style="font-family: Lucida Console">{</span><br /><span style="font-family: Lucida Console">public: </span><br /><span style="font-family: Lucida Console">virtual ~Derived() { cout&lt;&lt; "~Derived" &lt;&lt; endl ; }</span><br /><span style="font-family: Lucida Console">};</span><br /><br /><span style="font-family: Lucida Console">void main(void)</span><br /><span style="font-family: Lucida Console">{</span><br /><span style="font-family: Lucida Console">Base * pB = new Derived; // upcast</span><br /><span style="font-family: Lucida Console">delete pB;</span><br /><span style="font-family: Lucida Console">}</span></div><span style="font-family: Lucida Console">输出结果为：</span><br /><span style="font-family: Lucida Console">~Derived</span><br /><span style="font-family: Lucida Console">~Base</span><br /><br /><span style="font-family: Lucida Console">如果析构函数不为虚，那么输出结果为</span><br /><span style="font-family: Lucida Console">~Base</span><br /><br /><strong><span style="font-family: Lucida Console; color: red">十八、#IFNDEF/#DEFINE/#ENDIF有什么作用</span></strong><br /><span style="font-family: Lucida Console">仿止该头文件被重复引用 </span><br /><br />
<h3><span style="font-family: Lucida Console">评论</span></h3>
<h4><a title="permalink: re: C++高效编程忠告" href="http://www.cppblog.com/mzty/archive/2007/07/19/28359.html#28377"><span style="font-family: Lucida Console">#</span></a>&nbsp;<a name="28377"></a><span style="font-family: Lucida Console">re: C++高效编程忠告 </span><span style="font-family: Lucida Console">2007-07-19 19:21 </span><a id="AjaxHolder_Comments_CommentList_ctl00_NameLink" href="http://www.cppblog.com/ly4cn/" target="_blank"><span style="font-family: Lucida Console">沐枫</span></a> </h4>
<p><span style="font-family: Lucida Console">闲来无聊，无聊一下：</span><br /><br /><span style="font-family: Lucida Console">2 头文件的作用</span><br /><span style="font-family: Lucida Console">这是由于历史原因造成的。</span><br /><span style="font-family: Lucida Console">头文件主要用于存放接口声明，以便不同的c文件共享函数声明。</span><br /><span style="font-family: Lucida Console">到了c++中，已经造成一种妨碍了。</span><br /><br /><span style="font-family: Lucida Console">3 * &amp; 的位置</span><br /><span style="font-family: Lucida Console">这个位置放哪，虽然要紧，但更要紧的是，遵守一个变量一行定义。这样就不会出现错误，也很好读。如：</span><br /><span style="font-family: Lucida Console">int * i;</span><br /><span style="font-family: Lucida Console">int j;</span><br /><br /><span style="font-family: Lucida Console">4 if</span><br /><span style="font-family: Lucida Console">仍然是历史原因造成的。c标准中没有真正的bool类型(c++98和c99加了)，而是用int来代替，这就造成了麻烦。所以新写的程序要避免使用BOOL，而用bool来替代。</span><br /><span style="font-family: Lucida Console">如果是旧标准的编译器，仍然要注意BOOL其实是int这个要点。</span><br /><br /><span style="font-family: Lucida Console">5 const #define enum</span><br /><span style="font-family: Lucida Console">这几个各有用途，有时候也不能互代。使用时，优先顺序 enum const #define。看具体要求，不一定非要怎么怎么样。</span><br /><br /><span style="font-family: Lucida Console">6 参数传递</span><br /><span style="font-family: Lucida Console">用指针或用引用，倒不定要要争个谁好谁坏。</span><br /><span style="font-family: Lucida Console">实际上，用指针还更容易让人明白传进去的是指针。而引用则不然。引用的引入，在c++中是为了解决运算符重载的问题。</span><br /><span style="font-family: Lucida Console">不过，不管用哪个，倒是建议优先采用 const T* 或const T&amp;，这种常量指针或常亘引用。这不仅关系程序优化，也关系到代码的质量。</span><br /><br /><span style="font-family: Lucida Console">8 memcpy</span><br /><span style="font-family: Lucida Console">除非没有类似的库函数，否则不要重新写一个。要知道，绝大多数编译器会对这些库函数作特殊优化。这是手工编码无法做到的。</span><br /><br /><span style="font-family: Lucida Console">11 字串</span><br /><span style="font-family: Lucida Console">建议不要使用strcpy,strcmp类似的函数，应该改为strncpy, strncmp等函数。目前新型的编译器会认为strxxx函数是非法的（被淘汰的），建议用strnxxx，或者编译器提供的更安全的版本。</span><br /><br /><span style="font-family: Lucida Console">13 指针的大小</span><br /><span style="font-family: Lucida Console">与编译器及系统平台有关。大小从2/4/8/16各种可能性都有.不要认死了。</span><br /><br /><span style="font-family: Lucida Console">14 关于new/delete 与malloc/free</span><br /><span style="font-family: Lucida Console">你用了类似class的关键字后，就注定不兼容于c了。因此，用了c++的东西，就不要去用mallco/free，除非特殊情况。</span><br /><span style="font-family: Lucida Console">同理，不使用c++的东西，也决不要去用new /delete.</span><br /><span style="font-family: Lucida Console">否则，你的跨语言或跨平台的想法就打水漂了。还容易出错。</span><br /><br /><span style="font-family: Lucida Console">15 const 函数</span><br /><span style="font-family: Lucida Console">const不一定只能引用const成员。它可以使用任何成员，只是默认情况不能改变成员的值而已。如果成员被定义为mutable（c++98)，则不限制。</span><br /><br /><span style="font-family: Lucida Console">18 #ifdef</span><br /><span style="font-family: Lucida Console">说的太绝对了。而且没有任何说明如何做。</span><br /><span style="font-family: Lucida Console">事实上#ifdef能做的事还是挺多的。&nbsp;&nbsp;</span><a onclick='return SetReplyAuhor("沐枫")' href="http://www.cppblog.com/mzty/archive/2007/07/19/28359.html#post"><span style="font-family: Lucida Console">回复</span></a>&nbsp;&nbsp;<a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e6%b2%90%e6%9e%ab" target="_blank"><span style="font-family: Lucida Console">更多评论</span></a> <a id="AjaxHolder_Comments_CommentList_ctl00_DeleteLink" href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl00$DeleteLink','')"></a>&nbsp;&nbsp;<a id="AjaxHolder_Comments_CommentList_ctl00_EditLink"></a> </p>
<h4><a title="permalink: re: C++高效编程忠告" href="http://www.cppblog.com/mzty/archive/2007/07/19/28359.html#28385"><span style="font-family: Lucida Console">#</span></a>&nbsp;<a name="28385"></a><span style="font-family: Lucida Console">re: C++高效编程忠告 </span><span style="font-family: Lucida Console">2007-07-19 21:44 </span><a id="AjaxHolder_Comments_CommentList_ctl01_NameLink" href="http://www.cppblog.com/mzty/" target="_blank"><span style="font-family: Lucida Console">梦在天涯</span></a> </h4>
<p><span style="font-family: Lucida Console">恩，楼上说的很好，可见C++的功底之强，学习中。。。&nbsp;&nbsp;</span><a onclick='return SetReplyAuhor("梦在天涯")' href="http://www.cppblog.com/mzty/archive/2007/07/19/28359.html#post"><span style="font-family: Lucida Console">回复</span></a>&nbsp;&nbsp;<a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e6%a2%a6%e5%9c%a8%e5%a4%a9%e6%b6%af" target="_blank"><span style="font-family: Lucida Console">更多评论</span></a> <a id="AjaxHolder_Comments_CommentList_ctl01_DeleteLink" href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl01$DeleteLink','')"></a>&nbsp;&nbsp;<a id="AjaxHolder_Comments_CommentList_ctl01_EditLink"></a> </p>
<h4><a title="permalink: re: C++高效编程忠告" href="http://www.cppblog.com/mzty/archive/2007/07/19/28359.html#28402"><span style="font-family: Lucida Console">#</span></a>&nbsp;<a name="28402"></a><span style="font-family: Lucida Console">re: C++高效编程忠告 </span><span style="font-family: Lucida Console">2007-07-20 09:33 </span><a id="AjaxHolder_Comments_CommentList_ctl02_NameLink" href="http://www.cppblog.com/jinq0123/" target="_blank"><span style="font-family: Lucida Console">金庆</span></a> </h4>
<p><span style="font-family: Lucida Console">三、* , &amp;修饰符的位置</span><br /><span style="font-family: Lucida Console">int* &amp; rY = pI; // ptr's ref</span><br /><span style="font-family: Lucida Console">用int*表示指针更清楚。</span><br /><br /><span style="font-family: Lucida Console">int *i,j;</span><br /><span style="font-family: Lucida Console">我更倾向于这样分开写:</span><br /><span style="font-family: Lucida Console">int * pI;</span><br /><span style="font-family: Lucida Console">int j;</span><br /><br /><span style="font-family: Lucida Console">六、C++函数中值的传递方式</span><br /><span style="font-family: Lucida Console">&#8220;如果输入参数是以值传递的话，最好使用引用传递代替&#8221;</span><br /><span style="font-family: Lucida Console">应该是&#8220;如果输入参数是常量值的话，最好使用常量引用传递代替&#8221;。</span><br /><span style="font-family: Lucida Console">但是简单常量就不需要引用传递。</span><br /><br /><span style="font-family: Lucida Console">十二、sizeof的问题</span><br /><span style="font-family: Lucida Console">一般没有这样定义函数的:</span><br /><span style="font-family: Lucida Console">void fun(char a[1000])</span><br /><span style="font-family: Lucida Console">而是void fun(char * p, int len)&nbsp;&nbsp;</span><a onclick='return SetReplyAuhor("金庆")' href="http://www.cppblog.com/mzty/archive/2007/07/19/28359.html#post"><span style="font-family: Lucida Console">回复</span></a>&nbsp;&nbsp;<a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e9%87%91%e5%ba%86" target="_blank"><span style="font-family: Lucida Console">更多评论</span></a> <a id="AjaxHolder_Comments_CommentList_ctl02_DeleteLink" href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl02$DeleteLink','')"></a>&nbsp;&nbsp;<a id="AjaxHolder_Comments_CommentList_ctl02_EditLink"></a> </p>
<h4><a title="permalink: re: C++高效编程忠告" href="http://www.cppblog.com/mzty/archive/2007/07/19/28359.html#28404"><span style="font-family: Lucida Console">#</span></a>&nbsp;<a name="28404"></a><span style="font-family: Lucida Console">re: C++高效编程忠告 </span><span style="font-family: Lucida Console">2007-07-20 09:47 </span><a id="AjaxHolder_Comments_CommentList_ctl03_NameLink" href="http://www.cppblog.com/jinq0123/" target="_blank"><span style="font-family: Lucida Console">金庆</span></a> </h4>
<p><span style="font-family: Lucida Console">&#8220;头文件到了c++中，已经造成一种妨碍了&#8221;？</span><br /><span style="font-family: Lucida Console">能说明一下吗？</span><br /><br /><span style="font-family: Lucida Console">头文件在C++中还是必须的吧？</span><br /><br />&nbsp;&nbsp;<a onclick='return SetReplyAuhor("金庆")' href="http://www.cppblog.com/mzty/archive/2007/07/19/28359.html#post"><span style="font-family: Lucida Console">回复</span></a>&nbsp;&nbsp;<a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e9%87%91%e5%ba%86" target="_blank"><span style="font-family: Lucida Console">更多评论</span></a> <a id="AjaxHolder_Comments_CommentList_ctl03_DeleteLink" href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl03$DeleteLink','')"></a>&nbsp;&nbsp;<a id="AjaxHolder_Comments_CommentList_ctl03_EditLink"></a> </p>
<h4><a title="permalink: re: C++高效编程忠告" href="http://www.cppblog.com/mzty/archive/2007/07/19/28359.html#28425"><span style="font-family: Lucida Console">#</span></a>&nbsp;<a name="28425"></a><span style="font-family: Lucida Console">re: C++高效编程忠告 </span><span style="font-family: Lucida Console">2007-07-20 12:00 </span><a id="AjaxHolder_Comments_CommentList_ctl04_NameLink" href="http://www.cppblog.com/ly4cn/" target="_blank"><span style="font-family: Lucida Console">沐枫</span></a> </h4>
<p><span style="font-family: Lucida Console">@金庆</span><br /><span style="font-family: Lucida Console">就是必须的，所以才是一种妨碍。</span><br /><br /><span style="font-family: Lucida Console">目前C++有3种编程：c, 类, 模板。</span><br /><span style="font-family: Lucida Console">其中，头文件对于c来说，并不成问题，甚至还带来许多便利。</span><br /><span style="font-family: Lucida Console">但是对于类，和模板，特别是模板来说，麻烦就大了。</span><br /><br /><span style="font-family: Lucida Console">对于类来说，封装性和实现隐藏是一个很重要的概念，但大多数情况下，许多人都不容易做到这一点。.h文件中会有许多私有的数据成员，甚至还有不少的函数实现（如inline函数），从而对封装性和实现隐藏造成破坏，造成编译依赖，进一步造成编译器的复杂度提高。最终为了避开这些问题，将会造成库设计要求的提高。</span><br /><br /><span style="font-family: Lucida Console">至于模板风格的编程就更不得了，目前几乎没有支持分离模板的编译器。况且即便分离了，又能怎么样？最终的结果是，大多的模板风格的程序，所有的代码都在.h文件中，.cpp反而只剩了一句话：#include "xxx.h"，没了。</span><br /><br />&nbsp;&nbsp;<a onclick='return SetReplyAuhor("沐枫")' href="http://www.cppblog.com/mzty/archive/2007/07/19/28359.html#post"><span style="font-family: Lucida Console">回复</span></a>&nbsp;&nbsp;<a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e6%b2%90%e6%9e%ab" target="_blank"><span style="font-family: Lucida Console">更多评论</span></a> <a id="AjaxHolder_Comments_CommentList_ctl04_DeleteLink" href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl04$DeleteLink','')"></a>&nbsp;&nbsp;<a id="AjaxHolder_Comments_CommentList_ctl04_EditLink"></a> </p>
<h4><a title="permalink: re: C++高效编程忠告[未登录]" href="http://www.cppblog.com/mzty/archive/2007/07/19/28359.html#28586"><span style="font-family: Lucida Console">#</span></a>&nbsp;<a name="28586"></a><span style="font-family: Lucida Console">re: C++高效编程忠告[未登录] </span><span style="font-family: Lucida Console">2007-07-22 21:18 </span><a id="AjaxHolder_Comments_CommentList_ctl05_NameLink" href="http://www.cppblog.com/mzty" target="_blank"><span style="font-family: Lucida Console">梦在天涯</span></a> </h4>
<p><span style="font-family: Lucida Console">对目前的编译器都不支持模板的分离，都必须在。h中实现。&nbsp;&nbsp;</span><a onclick='return SetReplyAuhor("梦在天涯")' href="http://www.cppblog.com/mzty/archive/2007/07/19/28359.html#post"><span style="font-family: Lucida Console">回复</span></a>&nbsp;&nbsp;<a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e6%a2%a6%e5%9c%a8%e5%a4%a9%e6%b6%af" target="_blank"><span style="font-family: Lucida Console">更多评论</span></a><br /><br /><span style="font-family: Lucida Console">本文转自：</span><a href="http://www.cppblog.com/mzty/archive/2007/07/19/28359.html"><span style="font-family: Lucida Console">http://www.cppblog.com/mzty/archive/2007/07/19/28359.html</span></a></p><img src ="http://www.cppblog.com/wanghaiguang/aggbug/193840.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2012-10-25 15:20 <a href="http://www.cppblog.com/wanghaiguang/archive/2012/10/25/193840.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++内存泄露的检测（转载）</title><link>http://www.cppblog.com/wanghaiguang/archive/2012/10/24/193770.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Wed, 24 Oct 2012 05:17:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2012/10/24/193770.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/193770.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2012/10/24/193770.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/193770.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/193770.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: C++内存泄露的检测（一） 一Visual Studio 调试器和 C 运行时 (CRT) 库为我们提供了检测和识别内存泄漏的有效方法。主要使用函数：_CrtDumpMemoryLeaks();二 实例#define&nbsp;_CRTDBG_MAP_ALLOC&nbsp;&nbsp;&nbsp;//输出更详细的report#include&nbsp;&lt;stdlib.h&gt;#incl...&nbsp;&nbsp;<a href='http://www.cppblog.com/wanghaiguang/archive/2012/10/24/193770.html'>阅读全文</a><img src ="http://www.cppblog.com/wanghaiguang/aggbug/193770.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2012-10-24 13:17 <a href="http://www.cppblog.com/wanghaiguang/archive/2012/10/24/193770.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++的异常传递方法</title><link>http://www.cppblog.com/wanghaiguang/archive/2012/10/24/193758.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Wed, 24 Oct 2012 02:20:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2012/10/24/193758.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/193758.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2012/10/24/193758.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/193758.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/193758.html</trackback:ping><description><![CDATA[<span style="font-family: Verdana; font-size: 12pt">C++函数后面后加到关键字throw(something)限制，是对这个函数的异常安全性作出限制。</span><br /><br /><span style="font-family: Verdana; font-size: 12pt">void f() throw()&nbsp; 表示f不允许抛出任何异常，即f是异常安全的。</span><br /><br /><span style="font-family: Verdana; font-size: 12pt">void f() throw(...) 表示f可以抛出任何形式的异常。</span><br /><br /><span style="font-family: Verdana; font-size: 12pt">void f() throw(exceptionType); 表示f只能抛出exceptionType类型的异常。</span><br /><br /><span style="font-family: Verdana; font-size: 12pt">引别人的一个笑话：</span><br /><br /><span style="font-family: Verdana; font-size: 12pt">throw() 大概会说：&#8220;噢，不管你抛什么，就是不准抛。。&#8221;</span><br /><span style="font-family: Verdana; font-size: 12pt">throw(...) 呵呵一笑，满脸慈祥：&#8220;抛吧抛吧，尽情地抛吧。。。&#8221;</span><br /><span style="font-family: Verdana; font-size: 12pt">throw(type) 一听急了：&#8220;那可不行，要抛也只能抛我的香烟头，否则要是不小心把俺祖传的金戒指抛掉就太亏了。。。&#8221;</span><br /><br /><span style="font-family: Verdana; font-size: 12pt">关于C++的异常传递有三种方法：</span><br /><br /><span style="font-family: Verdana; font-size: 12pt">1.传值(by value)</span><br /><br /><span style="font-family: Verdana; font-size: 12pt">传值的过程中会产生临时对象的拷贝，不能解决多态的问题，如下：myexception继承exception，但是但确无法被正确的调用myexception的方法，造成对异常对象的切割。 </span>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;myexception:</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;exception{<br /></span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br /></span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">virtual</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;what()&nbsp;</span><span style="color: #0000ff">throw</span><span style="color: #000000">();<br /></span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #000000">};<br /></span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;myexception::what(){<br /></span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">myException</span><span style="color: #000000">"</span><span style="color: #000000">;<br /></span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #000000">}<br /></span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;A{<br /></span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br /></span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;A(){}<br /></span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;f()&nbsp;</span><span style="color: #0000ff">throw</span><span style="color: #000000">(){<br /></span><span style="color: #008080">12</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">throw</span><span style="color: #000000">&nbsp;myexception();<br /></span><span style="color: #008080">13</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">14</span>&nbsp;<span style="color: #000000">};<br /></span><span style="color: #008080">15</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;main(){<br /></span><span style="color: #008080">16</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;a;<br /></span><span style="color: #008080">17</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">try</span><span style="color: #000000">{<br /></span><span style="color: #008080">18</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a.f();<br /></span><span style="color: #008080">19</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000ff">catch</span><span style="color: #000000">(exception&nbsp;exc){<br /></span><span style="color: #008080">20</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">exc.what();<br /></span><span style="color: #008080">21</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">22</span>&nbsp;<span style="color: #000000">}</span></div><br /><span style="font-family: Verdana; font-size: 12pt">运行结果：UnKnown exceptions</span><br /><br /><span style="font-family: Verdana; font-size: 12pt">程序执行是会调用exception的what方法，而不是myexception的what方法。</span><br /><br /><span style="font-family: Verdana; font-size: 12pt">2.传指针(by pointer)</span><br /><br /><span style="font-family: Verdana; font-size: 12pt">指针可以实现多态，但往往会将临时对象的地址作为指针传出去，出现悬挂指针错误。如果在堆上分配内存空间，又往往不知道何时删除对</span>象，出现to be or not to be的错误。<br /><br />结果显示：myException
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;myexception:</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;exception{<br /></span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br /></span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">virtual</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;what()&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">;<br /></span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #000000">};<br /></span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;myexception::what()&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">{<br /></span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">myException</span><span style="color: #000000">"</span><span style="color: #000000">;<br /></span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #000000">}<br /></span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;A{<br /></span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br /></span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;A(){}<br /></span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;f()&nbsp;</span><span style="color: #0000ff">throw</span><span style="color: #000000">(){<br /></span><span style="color: #008080">12</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">throw</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;myexception();<br /></span><span style="color: #008080">13</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">14</span>&nbsp;<span style="color: #000000">};<br /></span><span style="color: #008080">15</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;main(){<br /></span><span style="color: #008080">16</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;a;<br /></span><span style="color: #008080">17</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">try</span><span style="color: #000000">{<br /></span><span style="color: #008080">18</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a.f();<br /></span><span style="color: #008080">19</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000ff">catch</span><span style="color: #000000">(exception</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;pexc){<br /></span><span style="color: #008080">20</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">pexc</span><span style="color: #000000">-&gt;</span><span style="color: #000000">what();<br /></span><span style="color: #008080">21</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;pexc;<br /></span><span style="color: #008080">22</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">23</span>&nbsp;<span style="color: #000000">}</span></div><br />3.传引用(by reference)<br /><br />传引用是最好的方法，可以克服前面的两个问题。<br /><br />程序结果显示:myException<br /><br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;myexception:</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;exception{<br /></span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br /></span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">virtual</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;what()&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">;<br /></span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #000000">};<br /></span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;myexception::what()&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">{<br /></span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">myException</span><span style="color: #000000">"</span><span style="color: #000000">;<br /></span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #000000">}<br /></span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;A{<br /></span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br /></span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;A(){}<br /></span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;f()&nbsp;</span><span style="color: #0000ff">throw</span><span style="color: #000000">(){<br /></span><span style="color: #008080">12</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">throw</span><span style="color: #000000">&nbsp;myexception();<br /></span><span style="color: #008080">13</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">14</span>&nbsp;<span style="color: #000000">};<br /></span><span style="color: #008080">15</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;main(){<br /></span><span style="color: #008080">16</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;a;<br /></span><span style="color: #008080">17</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">try</span><span style="color: #000000">{<br /></span><span style="color: #008080">18</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a.f();<br /></span><span style="color: #008080">19</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000ff">catch</span><span style="color: #000000">(exception</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;exc){<br /></span><span style="color: #008080">20</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">exc.what();<br /></span><span style="color: #008080">21</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">22</span>&nbsp;<span style="color: #000000">}</span></div><br />本文转自：<a href="http://www.cnblogs.com/CUCmehp/archive/2009/01/12/1374320.html">http://www.cnblogs.com/CUCmehp/archive/2009/01/12/1374320.html</a><img src ="http://www.cppblog.com/wanghaiguang/aggbug/193758.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2012-10-24 10:20 <a href="http://www.cppblog.com/wanghaiguang/archive/2012/10/24/193758.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IOCP模型总结</title><link>http://www.cppblog.com/wanghaiguang/archive/2012/10/23/193723.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Tue, 23 Oct 2012 06:46:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2012/10/23/193723.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/193723.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2012/10/23/193723.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/193723.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/193723.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: IOCP模型总结IOCP（I/O Completion Port，I/O完成端口）是性能最好的一种I/O模型。它是应用程序使用线程池处理异步I/O请求的一种机制。在处理多个并发的异步I/O请求时，以往的模型都是在接收请求是创建一个线程来应答请求。这样就有很多的线程并行地运行在系统中。而这些线程都是可运行的，Windows内核花费大量的时间在进行线程的上下文切换，并没有多少时间花在线程运行上。再加上...&nbsp;&nbsp;<a href='http://www.cppblog.com/wanghaiguang/archive/2012/10/23/193723.html'>阅读全文</a><img src ="http://www.cppblog.com/wanghaiguang/aggbug/193723.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2012-10-23 14:46 <a href="http://www.cppblog.com/wanghaiguang/archive/2012/10/23/193723.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++的异常处理</title><link>http://www.cppblog.com/wanghaiguang/archive/2012/10/22/193676.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Mon, 22 Oct 2012 09:30:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2012/10/22/193676.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/193676.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2012/10/22/193676.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/193676.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/193676.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一、什么是异常处理&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一句话：异常处理就是处理程序中的错误。二、为什么需要异常处理，以及异常处理的基本思想&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; C++之父Bjarne Stroustrup在《The C++ Programming Language》中讲到：...&nbsp;&nbsp;<a href='http://www.cppblog.com/wanghaiguang/archive/2012/10/22/193676.html'>阅读全文</a><img src ="http://www.cppblog.com/wanghaiguang/aggbug/193676.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2012-10-22 17:30 <a href="http://www.cppblog.com/wanghaiguang/archive/2012/10/22/193676.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>堆栈相关知识</title><link>http://www.cppblog.com/wanghaiguang/archive/2012/09/21/191464.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Fri, 21 Sep 2012 05:04:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2012/09/21/191464.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/191464.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2012/09/21/191464.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/191464.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/191464.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一、预备知识—程序的内存分配<br>一个由c/C++编译的程序占用的内存分为以下几个部分<br>1、栈区（stack）— 由编译器自动分配释放 ，存放函数的参数值，局部变量的值等。其操作方式类似于数据结构中的栈。<br>2、堆区（heap） — 一般由程序员分配释放， 若程序员不释放，程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事，分配方式倒是类似于链表，呵呵。<br>3、全局区（静态区）（static）—，全局变量和静态变量的存储是放在一块的，初始化的全局变量和静态变量在一块区域， 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放 <br>4、文字常量区—常量字符串就是放在这里的。 程序结束后由系统释放<br>5、程序代码区—存放函数体的二进制代码。<br>&nbsp;&nbsp;<a href='http://www.cppblog.com/wanghaiguang/archive/2012/09/21/191464.html'>阅读全文</a><img src ="http://www.cppblog.com/wanghaiguang/aggbug/191464.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2012-09-21 13:04 <a href="http://www.cppblog.com/wanghaiguang/archive/2012/09/21/191464.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IOCP与线程</title><link>http://www.cppblog.com/wanghaiguang/archive/2012/09/20/191383.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Thu, 20 Sep 2012 05:12:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2012/09/20/191383.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/191383.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2012/09/20/191383.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/191383.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/191383.html</trackback:ping><description><![CDATA[<p><font size="2"><span style="font-size: 12pt">author : Kevin Lynx</span></font> 
<p><strong><font size="1"></font></strong>&nbsp; 
<p><strong style="font-size: 12pt">什么是完成包？</strong> 
<p><font size="2"><span style="font-size: 12pt">完成包，即IO Completion Packet，是指异步IO操作完毕后OS提交给应用层的通知包。IOCP维护了一个IO操作结果队列，里面</span><br /><span style="font-size: 12pt">保存着各种完成包。应用层调用GQCS(也就是GetQueueCompletionStatus)函数获取这些完成包。 </span></font>
<p><font size="2"><strong style="font-size: 12pt">最大并发线程数</strong> </font>
<p><font size="2"><span style="font-size: 12pt">在一个典型的IOCP程序里，会有一些线程调用GQCS去获取IO操作结果。最大并发线程数指定在同一时刻处理完成包的线程数目。</span><br /><span style="font-size: 12pt">该参数在调用CreateIoCompletionPort时由NumberOfConcurrentThreads指定。 </span></font>
<p><font size="2"><strong style="font-size: 12pt">工作者线程</strong> </font>
<p><font size="2"><span style="font-size: 12pt">工作者线程一般指的就是调用GQCS函数的线程。要注意的是，工作者线程数和最大并发线程数并不是同一回事(见下文)。工作者</span><br /><span style="font-size: 12pt">线程由应用层显示创建(_beginthreadex 之类)。工作者线程通常是一个循环，会不断地GQCS到完成包，然后处理完成包。 </span></font>
<p><font size="2"><strong style="font-size: 12pt">调度过程</strong> </font>
<p><font size="2"><span style="font-size: 12pt">工作者线程以是否阻塞分为两种状态：运行状态和等待状态。当线程做一些阻塞操作时(线程同步，甚至GQCS空的完成队列)，线程</span><br /><span style="font-size: 12pt">处于等待状态；否则，线程处于运行状态。 </span></font>
<p><font size="2"><span style="font-size: 12pt">另一方面，OS会始终保持某一时刻处于运行状态的线程数小于最大并发线程数。每一个调用GQCS函数的线程OS实际上都会进行记录，</span><br /><span style="font-size: 12pt">当完成队列里有完成包时，OS会首先检查当前处于运行状态的工作线程数是否小于最大并发线程数，如果小于，OS会按照LIFO的顺</span><br /><span style="font-size: 12pt">序让某个工作者线程从GQCS返回(此工作者线程转换为运行状态)。如何决定这个LIFO？这是简单地通过调用GQCS函数的顺序决定的。 </span></font>
<p><font size="2"><span style="font-size: 12pt">从这里可以看出，这里涉及到线程唤醒和睡眠的操作。如果两个线程被放置于同一个CPU上，就会有线程切换的开销。因此，为了消</span><br /><span style="font-size: 12pt">除这个开销，最大并发线程数被建议为设置成CPU数量。 </span></font>
<p><font size="2"><span style="font-size: 12pt">从以上调度过程还可以看出，如果某个处于运行状态的工作者线程在处理完成包时阻塞了(例如线程同步、其他IO操作)，那么就有</span><br /><span style="font-size: 12pt">CPU资源处于空闲状态。因此，我们也看到很多文档里建议，工作者线程数为(CPU数*2+2)。 </span></font>
<p><font size="2"><span style="font-size: 12pt">在一个等待线程转换到运行状态时，有可能会出现短暂的时间运行线程数超过最大并发线程数，这个时候OS会迅速地让这个新转换</span><br /><span style="font-size: 12pt">的线程阻塞，从而减少这个数量。(关于这个观点，MSDN上只说：by not allowing any new active threads，却没说明not allowing</span><br /><span style="font-size: 12pt">what) </span></font>
<p><font size="2"><strong style="font-size: 12pt">调度原理</strong> </font>
<p><font size="2"><span style="font-size: 12pt">这个知道了其实没什么意义，都是内核做的事，大致上都是操作线程control block，直接摘录&lt;Inside IO Completion Ports&gt;: </span></font>
<p><font size="2"><span style="font-size: 12pt">The list of threads hangs off the queue object. A thread's control block data structure has a pointer in it that </span><br /><span style="font-size: 12pt">references the queue object of a queue that it is associated with; if the pointer is NULL then the thread is not </span><br /><span style="font-size: 12pt">associated with a queue. </span></font>
<p><font size="2"><span style="font-size: 12pt">So how does NT keep track of threads that become inactive because they block on something other than the completion</span><br /><span style="font-size: 12pt">port" The answer lies in the queue pointer in a thread's control block. The scheduler routines that are executed </span><br /><span style="font-size: 12pt">in response to a thread blocking (KeWaitForSingleObject, KeDelayExecutionThread, etc.) check the thread's queue </span><br /><span style="font-size: 12pt">pointer and if its not NULL they will call KiActivateWaiterQueue, a queue-related function. KiActivateWaiterQueue</span><br /><span style="font-size: 12pt">decrements the count of active threads associated with the queue, and if the result is less than the maximum and </span><br /><span style="font-size: 12pt">there is at least one completion packet in the queue then the thread at the front of the queue's thread list is </span><br /><span style="font-size: 12pt">woken and given the oldest packet. Conversely, whenever a thread that is associated with a queue wakes up after </span><br /><span style="font-size: 12pt">blocking the scheduler executes the function KiUnwaitThread, which increments the queue's active count. </span></font>
<p><font size="2"><strong style="font-size: 12pt">参考资料</strong> </font>
<p><font size="2"><span style="font-size: 12pt">&lt;Inside I/O Completion Ports&gt;:</span><br /></font><a href="http://technet.microsoft.com/en-us/sysinternals/bb963891.aspx"><font size="2"><span style="font-size: 12pt">http://technet.microsoft.com/en-us/sysinternals/bb963891.aspx</span></font></a><br /><font size="2"><span style="font-size: 12pt">&lt;I/O Completion Ports&gt;:</span><br /></font><a href="http://msdn.microsoft.com/en-us/library/aa365198(VS.85).aspx"><font size="2"><span style="font-size: 12pt">http://msdn.microsoft.com/en-us/library/aa365198(VS.85).aspx</span></font></a><br /><font size="2"><span style="font-size: 12pt">&lt;INFO: Design Issues When Using IOCP in a Winsock Server&gt;:</span><br /></font><a href="http://support.microsoft.com/kb/192800/en-us/"><font size="2"><span style="font-size: 12pt">http://support.microsoft.com/kb/192800/en-us/</span></font></a><br /><br /><span style="font-size: 12pt">本文转自：</span><a href="http://www.cppblog.com/kevinlynx/archive/2008/06/23/54390.html"><span style="font-size: 12pt">http://www.cppblog.com/kevinlynx/archive/2008/06/23/54390.html</span></a></p><img src ="http://www.cppblog.com/wanghaiguang/aggbug/191383.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2012-09-20 13:12 <a href="http://www.cppblog.com/wanghaiguang/archive/2012/09/20/191383.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程类继承问题</title><link>http://www.cppblog.com/wanghaiguang/archive/2012/09/14/190662.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Fri, 14 Sep 2012 08:16:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2012/09/14/190662.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/190662.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2012/09/14/190662.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/190662.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/190662.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 考虑一下多线程代码，在设计上，App为了获取更多的功能，从Window派生，而App同时为了获取某个模块的回调(所谓的Listener)，App同时派生Listener，并将自己的指针交给另一个模块，另一个模块通过该指针多态回调到App的实现(对Listener规定的接口的implemention)。设计上只是一个很简单的Listener回调，在单线程模式下一切都很正常(后面我会罗列代码)，但是换...&nbsp;&nbsp;<a href='http://www.cppblog.com/wanghaiguang/archive/2012/09/14/190662.html'>阅读全文</a><img src ="http://www.cppblog.com/wanghaiguang/aggbug/190662.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2012-09-14 16:16 <a href="http://www.cppblog.com/wanghaiguang/archive/2012/09/14/190662.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++陷阱：virtual析构函数</title><link>http://www.cppblog.com/wanghaiguang/archive/2012/09/14/190650.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Fri, 14 Sep 2012 05:54:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2012/09/14/190650.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/190650.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2012/09/14/190650.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/190650.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/190650.html</trackback:ping><description><![CDATA[<p><span style="font-size: 12pt">有一天有个同事在通过vld调试一个内存泄漏问题，折腾了很久然后找到我。我瞥了一眼他的代码，发现问题和我曾经遇到的一模一样：</span></p>
<div class="highlight">
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; font-size: 12pt">&nbsp;1</span>&nbsp;<span style="color: #0000ff; font-size: 12pt">class</span><span style="color: #000000; font-size: 12pt">&nbsp;Base&nbsp;{<br /></span><span style="color: #008080; font-size: 12pt">&nbsp;2</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff; font-size: 12pt">public</span><span style="color: #000000; font-size: 12pt">:<br /></span><span style="color: #008080; font-size: 12pt">&nbsp;3</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; font-size: 12pt">~</span><span style="color: #000000; font-size: 12pt">Base();<br /></span><span style="color: #008080; font-size: 12pt">&nbsp;4</span>&nbsp;<span style="color: #000000; font-size: 12pt">};<br /></span><span style="color: #008080; font-size: 12pt">&nbsp;5</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080; font-size: 12pt">&nbsp;6</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff; font-size: 12pt">class</span><span style="color: #000000; font-size: 12pt">&nbsp;Derived&nbsp;:&nbsp;</span><span style="color: #0000ff; font-size: 12pt">public</span><span style="color: #000000; font-size: 12pt">&nbsp;Base&nbsp;{<br /></span><span style="color: #008080; font-size: 12pt">&nbsp;7</span>&nbsp;<span style="color: #000000; font-size: 12pt">privated:<br /></span><span style="color: #008080; font-size: 12pt">&nbsp;8</span>&nbsp;<span style="color: #000000; font-size: 12pt">&nbsp;&nbsp;&nbsp;&nbsp;std::vector</span><span style="color: #000000; font-size: 12pt">&lt;</span><span style="color: #0000ff; font-size: 12pt">int</span><span style="color: #000000; font-size: 12pt">&gt;</span><span style="color: #000000; font-size: 12pt">&nbsp;m_data;&nbsp;&nbsp;&nbsp;&nbsp;};<br /></span><span style="color: #008080; font-size: 12pt">&nbsp;9</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080; font-size: 12pt">10</span>&nbsp;<span style="color: #000000; font-size: 12pt">Base&nbsp;</span><span style="color: #000000; font-size: 12pt">*</span><span style="color: #000000; font-size: 12pt">obj&nbsp;</span><span style="color: #000000; font-size: 12pt">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff; font-size: 12pt">new</span><span style="color: #000000; font-size: 12pt">&nbsp;Derived();<br /></span><span style="color: #008080; font-size: 12pt">11</span>&nbsp;<span style="color: #000000; font-size: 12pt">delete&nbsp;obj;</span></div><br /><span style="font-size: 12pt">当然，实际代码比这个复杂得多(这也是导致从发现问题到找到问题耗费大量时间的原因)。vld在报内存泄漏时，当然报的位置是</span><code><span style="font-size: 12pt">new</span></code><span style="font-size: 12pt">的地方。这个同事检查了这个对象的整个生命周期，确定他正确地释放了这个对象。</span></div>
<p><span style="font-size: 12pt">问题的关键就在于：</span><strong><code><span style="font-size: 12pt">Base</span></code></strong><strong style="font-size: 12pt">类的析构函数不是<code>virtual</code>的</strong><span style="font-size: 12pt">。因为不是</span><code style="font-size: 12pt">virtual</code><span style="font-size: 12pt">，所以在对一个</span><code style="font-size: 12pt">Base</code><span style="font-size: 12pt">类型的指针进行</span><code style="font-size: 12pt">delete</code><span style="font-size: 12pt">时，就不会调用到派生类</span><code style="font-size: 12pt">Derived</code><span style="font-size: 12pt">的析构函数。而派生类里的析构函数会用于析构其内部的子对象，也就是这里的</span><code style="font-size: 12pt">m_data</code><span style="font-size: 12pt">。这样，就造成了内存泄漏。</span></p>
<p><span style="font-size: 12pt">这其实是一个很低级的失误。但毫不客气地说C++中有很多这种少个关键字或者代码位置不对就会造成另一个结果的例子。事实上，针对这些悲剧也有很多书提出一些准则来让大家去无脑遵守。例如针对这个例子，我就记得曾有书说，只要你觉得你的类会被继承，那么最好给析构函数加上virtual。</span><br /></p>
<p class="post-footer"><span style="font-size: 12pt">原文地址： </span><a href="http://codemacro.com/2012/09/13/c-plus-plus-virtual-destructor/"><font color="#cc6666"><span style="font-size: 12pt">http://codemacro.com/2012/09/13/c-plus-plus-virtual-destructor/</span></font></a><br /><span style="font-size: 12pt">written by </span><a href="http://codemacro.com/"><font color="#cc6666"><span style="font-size: 12pt">Kevin Lynx</span></font></a><span style="font-size: 12pt"> &nbsp;posted at </span><a href="http://codemacro.com/"><font color="#cc6666"><span style="font-size: 12pt">http://codemacro.com</span></font></a> <br /><br /><span style="font-size: 12pt">本文转自：</span><a href="http://www.cppblog.com/kevinlynx/archive/2012/09/13/190541.html"><span style="font-size: 12pt">http://www.cppblog.com/kevinlynx/archive/2012/09/13/190541.html</span></a></p><img src ="http://www.cppblog.com/wanghaiguang/aggbug/190650.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2012-09-14 13:54 <a href="http://www.cppblog.com/wanghaiguang/archive/2012/09/14/190650.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows API 函数GetVersionEx 获取系统版本出错</title><link>http://www.cppblog.com/wanghaiguang/archive/2012/09/14/190619.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Fri, 14 Sep 2012 03:23:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2012/09/14/190619.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/190619.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2012/09/14/190619.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/190619.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/190619.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: win7下得到操作系统版本错误（ GetVersionEx）有一段得到操作系统版本的代码，用的是&nbsp;GetVersionEx&nbsp;方法，在当前机器的硬盘上运行，得到的操作系统版本是win7。奇怪的是，在U盘上运行，得到的操作系统版本是XP。直接说原因：　　不知道什么时候，系统在注册表中设置了U盘exe的XP兼容项（在兼容性助手弹出时，选择重新启动或者重新安装时，系统会在H...&nbsp;&nbsp;<a href='http://www.cppblog.com/wanghaiguang/archive/2012/09/14/190619.html'>阅读全文</a><img src ="http://www.cppblog.com/wanghaiguang/aggbug/190619.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2012-09-14 11:23 <a href="http://www.cppblog.com/wanghaiguang/archive/2012/09/14/190619.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++实用技巧——单元测试</title><link>http://www.cppblog.com/wanghaiguang/archive/2012/09/12/190392.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Wed, 12 Sep 2012 06:54:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2012/09/12/190392.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/190392.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2012/09/12/190392.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/190392.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/190392.html</trackback:ping><description><![CDATA[<div class="postTitle"><a id="viewpost1_TitleUrl" class="postTitle2" href="http://www.cppblog.com/vczh/archive/2010/06/27/118829.html">C++实用技巧（四）</a> </div>&nbsp;&nbsp;&nbsp; 复杂的东西写多了，如今写点简单的好了。由于功能上的需要，<a style="text-decoration: underline" href="http://vlpp.codeplex.com/" target="_blank">Vczh Library++3.0</a>被我搞得很离谱。为了开发维护的遍历、减少粗心犯下的错误以及增强单元测试、回归测试和测试工具，因此记录下一些开发上的小技巧，以便抛砖引玉，造福他人。欢迎高手来喷，菜鸟膜拜。<br /><br />&nbsp;&nbsp;&nbsp; <a style="text-decoration: underline" href="http://www.cppblog.com/vczh/archive/2010/06/24/118635.html" target="_blank">之前的文章</a>讲了指针和内存的一些问题，今天说一下单元测试的问题。如果在团队里面没有对单元测试的框架有要求的话，其实我们可以使用一个最简单的方法来搭建在IDE里面运行的单元测试框架，整个框架只需十几行代码。我们先来考虑一下功能最少的单元测试框架需要完成什么样的内容。首先我们要运行一个一个的测试用例，其次在一个测试用例里面我们要检查一些条件是否成立。举个例子，我们写一个函数将两个字符串连接起来，一般来说要进行下面的测试：<br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">MyUnitTestFramework.h</span><span style="color: #000000">"</span><span style="color: #008000">//</span><span style="color: #008000">等一下我们会展示一下如何用最少的代码完成这个头文件的内容</span><span style="color: #008000"><br /></span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #008000"></span><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000"><img src="http://www.cppblog.com/Images/dot.gif"  alt="" /></span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #000000">TEST_CASE(StringConcat)<br /></span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #000000">{<br /></span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;TEST_ASSERT(concat(</span><span style="color: #000000">"</span><span style="color: #000000">a</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">b</span><span style="color: #000000">"</span><span style="color: #000000">)</span><span style="color: #000000">==</span><span style="color: #000000">"</span><span style="color: #000000">ab</span><span style="color: #000000">"</span><span style="color: #000000">);<br /></span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;TEST_ASSERT(concat(</span><span style="color: #000000">"</span><span style="color: #000000">a</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">""</span><span style="color: #000000">)</span><span style="color: #000000">==</span><span style="color: #000000">"</span><span style="color: #000000">a</span><span style="color: #000000">"</span><span style="color: #000000">);<br /></span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;TEST_ASSERT(concat(</span><span style="color: #000000">""</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">b</span><span style="color: #000000">"</span><span style="color: #000000">)</span><span style="color: #000000">==</span><span style="color: #000000">"</span><span style="color: #000000">b</span><span style="color: #000000">"</span><span style="color: #000000">);<br /></span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;TEST_ASSERT(concat(</span><span style="color: #000000">""</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">""</span><span style="color: #000000">)</span><span style="color: #000000">==</span><span style="color: #000000">""</span><span style="color: #000000">);<br /></span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"  alt="" />.<br /></span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000">}<br /></span><span style="color: #008080">12</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">13</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;wmain()<br /></span><span style="color: #008080">14</span>&nbsp;<span style="color: #000000">{<br /></span><span style="color: #008080">15</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br /></span><span style="color: #008080">16</span>&nbsp;<span style="color: #000000">}</span></div><br />&nbsp;&nbsp;&nbsp; 如果我们的单元测试框架可以这么写，那显然做起什么事情来都会方便很多，而且不需要向一些其他的测试框架一样注册一大堆东西，或者是写一大堆配置函数。当然这次我们只做功能最少的测试框架，这个框架除了运行测试以外，不会有其他功能，譬如选择哪些测试可以运行啦，还是在出错的时候log一些什么啦之类。之所以要在IDE里面运行，是因为我们如果做到TEST_ASSERT中出现false的话，立刻在该行崩溃，那么IDE就会帮你定位到出错的TEST_ASSERT中去，然后给你显示所有的上下文信息，譬如说callstack啦什么的。友好的工具不用简直对不起自己啊，干吗非得把单元测试做得那么复杂捏，凡是单元测试，总是要全部运行通过才能提交代码的。<br /><br />&nbsp;&nbsp;&nbsp; 那么我们来看看上面的单元测试的代码。首先写了TEST_CASE的那个地方，大括号里面的代码会自动运行。其次TEST_ASSERT会在表达式是false的时候崩溃。先从简单的入手吧。如何制造崩溃呢？最简单的办法就是抛异常：<br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #008080">1</span>&nbsp;<span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;TEST_ASSERT(e)&nbsp;do(if(!(e))throw&nbsp;"今晚没饭吃。";}while(0)</span></div><br />&nbsp;&nbsp;&nbsp; 这里面有两个要注意的地方。首先e要加上小括号，不然取反操作符就有可能做出错误的行为。譬如说当e是a+b==c的时候，加了小括号就变成if(!(a+b==c))...，没有加小括号就变成if(!a+b==c)...，意思就完全变了。第二个主意的地方是我使用do{...}while(0)把语句包围起来了。这样做的好处是可以在任何时候TEST_ASSERT(e)都像一个语句。譬如我们可能这么写：<br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #008080">1</span>&nbsp;<span style="color: #0000ff">if</span><span style="color: #000000">(a)<br /></span><span style="color: #008080">2</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;TEST_ASSERT(x1);<br /></span><span style="color: #008080">3</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(b)<br /></span><span style="color: #008080">4</span>&nbsp;<span style="color: #000000">{<br /></span><span style="color: #008080">5</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;TEST_ASSERT(x2);<br /></span><span style="color: #008080">6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;TEST_ASSERT(x3);<br /></span><span style="color: #008080">7</span>&nbsp;<span style="color: #000000">}</span></div><br />&nbsp;&nbsp;&nbsp; 如果没有do{...}while(0)包围起来，这个else就会被绑定到宏里面的那个if，你的代码就被偷偷改掉了。<br /><br />&nbsp;&nbsp;&nbsp; 那么现在剩下TEST_CASE(x){y}了。什么东西可以在main函数外面自动运行呢？这个我想熟悉C++的人都会知道，就是全局变量的构造函数啦。所以TEST_CASE(x){y}那个大括号里面的y只能在全局变量的构造函数里面调用。但是我们知道写一个类的时候，构造函数的大括号写完了，后面还有类的大括号，全局变量的名称，和最终的一个分号。为了把这些去掉，那么显然{y}应该属于一个普通的函数。那么全局变量如何能够使用这个函数呢？方法很简单，把函数前置声明一下就行了：<br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;TEST_CASE(NAME)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">extern</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;TESTCASE_##NAME();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br /></span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">namespace</span><span style="color: #000000">&nbsp;vl_unittest_executors&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br /></span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br /></span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;TESTCASE_RUNNER_##NAME&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br /></span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br /></span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br /></span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TESTCASE_RUNNER_##NAME()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br /></span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br /></span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TESTCASE_##NAME();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br /></span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br /></span><span style="color: #008080">12</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;TESTCASE_RUNNER_##NAME##_INSTANCE;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br /></span><span style="color: #008080">13</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br /></span><span style="color: #008080">14</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;TESTCASE_##NAME()</span></div><br />&nbsp;&nbsp;&nbsp; 那我们来看看TEST_CASE(x){y}究竟会被翻译成什么代码：<br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #0000ff">extern</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;TESTCASE_x();<br /></span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">namespace</span><span style="color: #000000">&nbsp;vl_unittest_executors<br /></span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #000000">{<br /></span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;TESTCASE_RUNNER_x<br /></span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">:<br /></span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TESTCASE_RUNNER_x()<br /></span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TESTCASE_x();<br /></span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;TESTCASE_RUNNER_x_INSTANCE;<br /></span><span style="color: #008080">12</span>&nbsp;<span style="color: #000000">}<br /></span><span style="color: #008080">13</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;TESTCASE_x(){y}</span></div><br />&nbsp;&nbsp;&nbsp; 到了这里是不是很清楚了捏，首先在main函数运行之前TESTCASE_RUNNER_x_INSTANCE变量会初始化，然后调用TESTCASE_RUNNER_x的构造函数，最后运行函数TESTCASE_x，该函数的内容显然就是{y}了。这里还能学到宏是如何连接两个名字成为一个名字，和如何写多行的宏的。<br /><br />&nbsp;&nbsp;&nbsp; 于是MyUnittestFramework.h就包含这两个宏，其他啥都没有，是不是很方便呢？打开Visual C++，建立一个工程，引用这个头文件，然后写你的单元测试，最后F5就运行了，多方便啊，啊哈哈哈。<br /><br />&nbsp;&nbsp;&nbsp; 这里需要注意一点，那些单元测试的顺序是不受到保证的，特别是你使用了多个cpp文件的情况下。于是你在使用这个测试框架的同时，会被迫保证执行一次单元测试不会对你的全局状态带来什么副作用，以便两个测试用例交换顺序执行的时候仍然能稳定地产生相同的结果。这对你写单元测试有帮助，而且为了让你的代码能够被这么测试，你的代码也会写的有条理，不会依赖全局状态，真是一举两得也。而且说不定单元测试用例比你的全局变量的初始化还先执行呢，因此为了使用这个测试框架，你将会不得不把你的全局变量隐藏在一个cpp里面，而暴露出随时可以被调用的一组函数出来。这样也可以让你的代码在使用全局状态的时候更加安全。<br /><br />&nbsp;&nbsp;&nbsp; 今天就讲到这里了。下一篇要写什么我还没想好，到时候再说吧。 <br /><br />本文转自：<a href="http://www.cppblog.com/vczh/archive/2010/06/27/118829.html">http://www.cppblog.com/vczh/archive/2010/06/27/118829.html</a><img src ="http://www.cppblog.com/wanghaiguang/aggbug/190392.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2012-09-12 14:54 <a href="http://www.cppblog.com/wanghaiguang/archive/2012/09/12/190392.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++实用技巧——内存</title><link>http://www.cppblog.com/wanghaiguang/archive/2012/09/12/190391.html</link><dc:creator>王海光</dc:creator><author>王海光</author><pubDate>Wed, 12 Sep 2012 06:51:00 GMT</pubDate><guid>http://www.cppblog.com/wanghaiguang/archive/2012/09/12/190391.html</guid><wfw:comment>http://www.cppblog.com/wanghaiguang/comments/190391.html</wfw:comment><comments>http://www.cppblog.com/wanghaiguang/archive/2012/09/12/190391.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wanghaiguang/comments/commentRss/190391.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wanghaiguang/services/trackbacks/190391.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: C++实用技巧（一） &nbsp;&nbsp;&nbsp; 复杂的东西写多了，如今写点简单的好了。由于功能上的需要，Vczh Library++3.0被我搞得很离谱。为了开发维护的遍历、减少粗心犯下的错误以及增强单元测试、回归测试和测试工具，因此记录下一些开发上的小技巧，以便抛砖引玉，造福他人。欢迎高手来喷，菜鸟膜拜。&nbsp;&nbsp;&nbsp; C++实谓各种语言中的软肋，功能强大，陷阱...&nbsp;&nbsp;<a href='http://www.cppblog.com/wanghaiguang/archive/2012/09/12/190391.html'>阅读全文</a><img src ="http://www.cppblog.com/wanghaiguang/aggbug/190391.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wanghaiguang/" target="_blank">王海光</a> 2012-09-12 14:51 <a href="http://www.cppblog.com/wanghaiguang/archive/2012/09/12/190391.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>