windows、C++、MFC、Qt项目除错笔记

刚好今天解决了两个蛋疼的问题,就先记着,之后再补补以前的好了。

1.首先问题的现象是程序的Release版本崩溃了(Debug没有崩溃),崩溃的位置位于两个CString赋值,CString这货说实话,用了MFC这么久还真没怎么深究过,只依稀记得这货可动态改变缓冲区大小,且是通过引用计数进行内存释放的,一个赋值怎能崩溃?网上是查不到了的,因为这是不可能事件,只能自己找,我大概的解决路线如下:

(1)通过svn查看是因为加了一段代码导致,那段代码也就是简单的给wstring多赋了几个字符值,去掉则不崩溃,加上则崩溃,百思不得其解啊。

(2)崩溃的位置提示诡异,那么猜测有可能是内存损坏了,之后去检查相关调用,发现了问题的所在。

由于strlen本身是不计算\0的,在其中的一个类给char*赋值时,传入的len少给了一个\0的大小。

 

2.这个问题是关于多线程的,也是个蛋疼的问题,不过没有花费多少时间,总算是找到了。问题的现象是,MFC界面程序在经过某些操作之后,界面没有响应了(XP下发生,win7下正常)。任务管理器显示cpu为0,那么可以肯定不是死循环了,猜测到可能是多线程等待的问题。罪魁祸首是LeaveCriticalSection;由于某些同事的疏忽,在某个函数中调用了两次LeaveCriticalSection,导致后续调用EnterCriticalSection时程序等待,有点像死锁了。不过感觉还是微软实现的有问题,win7改了。

 

下面是补补之前的

3.多线程读写STL程序崩溃

同样遇到问题的人以及他们的解决方案:
http://www.tech-archive.net/Archive/VC/microsoft.public.vc.stl/2008-03/msg00027.html

我自己的解决方案是:通过发消息给窗体,等到主窗体的消息循环时,才进行处理,不直接调用接口,就可以避免多线程调用STL。

4.Windows TCP延迟问题:这个是之前做的多屏互动项目,需要通过TCP协议操作电脑,但由于TCP的延迟,导致效果不理想。找到了一个解决方案:

以下内容是从别处转载的:

TCP本身属面向链接的通讯协议。通讯双方的每一个收发动作,需要以通讯链路正常为前提。因此TCP协议内部提供了默认的ACK验证机制。而ACK验证方式存又与操作系统有关,在TCP中,对数据的确认往往是延迟的,在时延定时器没有溢出的情况下,一般情况是两个TCP数据对应一个确认,如果时延定时器溢出了,那么自然也会发送确认报文。但在某些系统中,会出现必须每次回复ACK包才继续发送TCP数据,这时就会出现以下问题:假定Server A、和Client B之间建立了一个TCP连接,某一时刻A第一次向B发送数据,发送完成后等待B回复的ACK包,而B认为收到第二个TCP数据包才回复ACK标记,则约200ms之后,B中的时延定时器溢出,B此时才向A回发一个长度为1的ACK确认包,因此B第二次收到数据时,会莫名其妙的产生一个约200ms的延时——这个延时不是别的,正是ACK确认包默认的发送时延。
      当我们测试自行研发的服务端通讯框架时,一旦其发生广播,则此时处于接收方的客户端很有可能会因为通讯双方的收发不均而引发上述现象——这并非是由于你的服务端通讯框架性能不达标,而是由于TCP的内部机制导致的。
那么,我们应该如何避免这种情况呢?这里介绍一种最简单也最容易实现的方法——修改注册表,提高客户端ACK包默认的发送频率,也就是缩短ACK包的发送时延:
首先,点击你电脑屏幕左下角的“开始”菜单,打开“运行”,键入“regedit”打开你的注册表;
选择HKEY_LOCAL_MACHINE 项目开始一层层的往下点,一直到
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/services/Tcpip/Parameters/Interfaces
这里是关于你网卡的数据,有很多项,且它们都有类似{5F26EBBD-9CA6-4219-9DBD-54852364EA17}这样的名字,但是正确的那个会在右边窗口显示包括你的IP地址和你的服务器IP地址等等网络设定)。 你找到IPAddress项符合你的本机IP地址的那个,那么它就是你连接网络的那个网卡的设定项,我们的任务目标就是改动它来提高客户端ACK包的发送频率。
其次,右键点击窗口右边的空白处,“新建”-“DWORD值”;
给它改名成“TcpAckFrequency”,然后右键点击它 ,选择"修改”,然后再那个"数值数据"的空白处填"1"(不用管是16进制,还是10进制)
最后,关闭注册表,重启电脑,修改完成。

有关TcpAckFrequency的补充说明:
TcpAckFrequency 值这个值确定了windows用TCP/IP 发送应答消息的频率,也就是决定了在发送“命令正确应答”之前将等候几个数据包;
默认值为 2,这时TCP/IP 将在接收到 2 个分段后发送应答,或是在接收了 1 个分段但在 200 毫秒内没有接收到其他分段的情况下发送应答
如果值为 3,则 TCP/IP 将在接收到 3 个分段后发送应答,或是在接收了 1 个或 2 个分段但在 200 毫秒内没有接收到其他分段的情况下发送应答,以此类推。
如果需要通过消除 TCP/IP 应答延迟来缩短响应时间,则将该值设为 1。在这种情况下,Windows将每收到一个TCP数据包就回送一个“命令正确应答”。
该值的有效范围是 0 到 255,其中 0 表示使用缺省值(2)。

采用Delayed ACK机制后,通常是服务端发送2个数据包后,客户端再进行确认,这样将极大的减少不必要的ACK数据包,同时也能提高访问速度,减少带宽浪费。
修改方法:
在注册表中添加键值进行修改;
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesTcpipParametersInterfacesAdapter GUID
值名称:TcpDelAckTicks(不同的操作系统该值的名称不尽相同)
数据类型:REG_DWORD
值数据:将该值设置为 0 到 6 之间的值
默认情况下,延迟 ACK 计时器值为 200 毫秒。如果将 TcpDelAckTicks 值设置为 0,则禁用延迟确认。

5.windows 7 高DPI UI错乱的解决办法

微软自己有提供解决方案,我们采用就可以了:

csdn上有个帖子:
http://bbs.csdn.net/topics/370177760

微软官方的解决方案:
http://msdn.microsoft.com/en-us/library/windows/desktop/dd464660(v=vs.85).aspx

微软给出了一个CDPI类封装了转换函数,之后可以用这个进行常规替换,解决起来应该是很方便的。



6.Win7多点触摸VS2010以及后续版本单点长按右键问题解决方案

做触摸应用这点很重要啊

http://connect.microsoft.com/VisualStudio/feedback/details/699523/tablet-pc-right-click-action-cannot-invoke-mfc-popup-menu

 

7.不能通过CCmdUI *pCmdUI改变对话框菜单状态的问题

 

需求描述:需要在对话框右键菜单做出类似word大纲级别的右键菜单

在普通的菜单中这个是很简单很简单的,但是由于在对话框中,动态创建菜单,并且在菜单前加上【•】 这样的选中符号。辛苦之后找到解决方案
Cause:
When a drop-down menu is displayed, the WM_INITMENUPOPUP message is sent prior to displaying the menu items. The MFCCFrameWnd::OnInitMenuPopup function iterates through the menu items and calls the update command UI handler for the item, if there is one. The appearance of each menu item is updated to reflect its state (enabled/disabled, checked/unchecked).

The update UI mechanism doesn't work for a dialog box-based application because CDialog has no OnInitMenuPopup handler and it uses CWnd's default handler, which does not call update command UI handlers for menu items.

Rusolution:
http://student.csdn.net/space.php?uid=44375&do=blog&id=38685

8.win 7窗体置顶问题(MFC)

相信很多人都遇到了,在网上搜索了很多方法,什么先AttachThreadInput到顶层窗体然后SetForegroundWindow,以及什么SystemParametersInfo关闭SPI_SETFOREGROUNDLOCKTIMEOUT属性,然后SetForegroundWindow在开启,能试的方法都试过了,都不能理想的让窗体置顶(MFC多文档窗体,有不同模式,需要在全屏模式下置顶),最后还是自己试验除了一套组合,

SetWindowPos(&wndTopMost,0,0,0,0,SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
::SetForegroundWindow(this->GetSafeHwnd());
SetWindowPos(0,0,0,0,0,SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);

前两个方法必须一起调用才有效果,最后那个是为了只置顶一次才添加。

你可能感兴趣的:(C++,Windows应用程序开发)