危险的两个函数GetCurrentDirectory和GetParent

最近这段时间用vc做了一个客户端程序,好长时间不做这种程序了,很是生疏,由于接手的别人的二手项目,大部分代码都已经完成了,只是跑起来问题很大,很多意料之中和意料之外的问题让人又爱又恨。其中遇到了两个函数造成的奇怪问题,好好分析找到了原因,都是一些平时不注意,对一些函数错误的使用造成的。下面说说这两个函数。

1、GetCurrentDirectory

DWORD WINAPI GetCurrentDirectory(
  __in   DWORD nBufferLength,
  __out  LPTSTR lpBuffer
);

这个是函数原型,他是主要是作用是获取程序的当前目录,大部分指的是当前运行程序所在的运行目录。记得这个地方说的是大部分情况,不是所有,有些特殊的情况会返回时其他的路径。我们的程序在运行中需要有监护程序来引导,当我写完监护程序让他引导进入主程序的时候发现了奇怪的问题,程序整个界面打乱,一张图片都没有,去目录下查找图片存在,而且直接运行主程序没有这个问题。我们在主程序里面跟踪也没有头绪,每个函数都运行的正常的出奇,没有一点不妥的。可是就是在监护程序引导的情况下出现异常。经过判断感觉是路径发面出现问题,导致找不到图片。我们查看获取路径的函数,发现使用了GetCurrentDirectory,这个获取当前目录的函数按照常理应该没有问题,细想我们是在监护程序里面使用的shell把主程序调用起来的,应该是忘记了设置工作目录造成的吧,于是修改监护程序,设置工作目录,依旧无果,特殊调试发现这个函数获得的路径是监护程序的位置,看来这个GetCurrentDirectory函数本身应该是出了问题,我们使用的错误。后来查看了一些资料,微软也承认这个函数有时候不是那么恰当,他的这个获取的值收到很多的影响,所以如果只是为了获取当前程序运行路径,建议使用GetModuleFileName这个函数来处理,这个比较准,因为他获得是当前运行程序的存储路径。我们的程序也是使用这个之后恢复正常的。

2、GetParent

这个函数就本身使用来说是没有什么问题,只是我们有些时候在开发桌面应用程序的时候需要用的某个窗口置顶的问题,通常解决方法就那几个setforegroud之类的,可是这些问题都受制于如果你的父窗口不直前你也别想在最前面,所以通常会用SetParent(NULL)函数来搞掉父窗口。当搞掉父窗口之后GetParent函数也就废掉了,获取的值是NULL的。很多时候在vc里面操作父类的界面都需要拿到父类的句柄,然后再获取父类里面的某些控件的值,例如子窗口获取父类列表当前选中的值。当窗口不值钱,用GetParent一切ok,后来为了置前弄了SetParent(NULL),编译无措,运行时候系统告诉你无效句柄,呵呵,这个问题好调出来,但是如果bug夺得焦头烂额的时候也是很难被发现的。对于这个的建议我们还是建议在基类里面默认设置一个包含父类句柄的变量,这样直接用就ok了。

上面的这些问题都是一些不良的编程习惯或者随意猜测函数弄出来的问题,总结上面的问题以后我再开始一个大型的c++项目之前一定要做好前期的设计,基础框架要做好,充分的用好几个好的设计模式,集中管理一些资源,界面等容易出现泄露问题的。等这个项目结束之后总结一些在大型C++项目里面基础框架必须包含的东西来分享一下。

posted on 2010-06-10 09:11 JesseZhao 阅读(3310) 评论(14) 编辑 收藏

评论

#1楼  回复 引用 查看   

Welcome Back.
原来你也是公路车爱好者,我现在每天骑单车上下班,感觉很舒服。
2010-06-10 09:17 | 晴天猪      

#2楼  回复 引用 查看   

GetCurrentDirectory 如果你使用了系统打开文件对话框或是写入文件是,当前的目录会变化的。还跟你设置的当前路径什么的有关系。
2010-06-10 09:34 | 曾灿      

#3楼  回复 引用 查看   

很好,谢谢分享!
当窗口不值钱 -> 当窗口不置前?
2010-06-10 10:35 | zdd      

#4楼  回复 引用 查看   

看上去,不像是C#程序。

#5楼  回复 引用 查看   

GetCurrentDirectory 这个基本属于废Api,只要用了,总有出错的一天。
2010-06-10 11:03 | CppCall      

#6楼  回复 引用 查看   

引用CppCall:GetCurrentDirectory 这个基本属于废Api,只要用了,总有出错的一天。

还有那个SetDirectory.
2010-06-10 12:05 | blackcat      

#7楼  回复 引用 查看   

错别字有点多,呵呵
2010-06-10 12:36 | Sabre      

#8楼  回复 引用 查看   

明明是调shell 的人忘记指定开始目录了 你却怪currentdirectory
这不是习惯不好 是基础不扎实

#9楼[楼主]  回复 引用 查看   

@韦恩卑鄙 v-zhewg @waynebaby
这个我在调用的时候给他设置了工作目录,可是还是不行,环境是vs2005+win7
2010-06-10 13:01 | JesseZhao      

#10楼  回复 引用 查看   

学习了。
2010-06-10 21:40 | 贤钟      

#11楼  回复 引用   

BOOL WINAPI CreateProcess(
__in LPCTSTR lpApplicationName,
__in_out LPTSTR lpCommandLine,
__in LPSECURITY_ATTRIBUTES lpProcessAttributes,
__in LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in BOOL bInheritHandles,
__in DWORD dwCreationFlags,
__in LPVOID lpEnvironment,
__in LPCTSTR lpCurrentDirectory,
__in LPSTARTUPINFO lpStartupInfo,
__out LPPROCESS_INFORMATION lpProcessInformation
);

lpCurrentDirectory不是写的很清楚了吗,这明明是调用者的责任,怎么能怪微软呢?
你倒给我们说说"于是修改监护程序,设置工作目录"是怎么设置的?
2010-06-11 00:01 | lgtam[未注册用户]

#12楼[楼主]  回复 引用 查看   

@lgtam
兄弟,这个参数不是每次都有效果的,我试验过的,
2010-06-11 08:48 | JesseZhao      

#13楼  回复 引用   

引用JesseZhao:
@lgtam
兄弟,这个参数不是每次都有效果的,我试验过的,

俺不信邪,你发代码试试。
2010-06-11 21:40 | lgtam[未注册用户]

#14楼  回复 引用 查看   

wchar_t szFullPath[MAX_PATH];
ZeroMemory(szFullPath, MAX_PATH);
::GetModuleFileName(NULL, szFullPath, MAX_PATH); //搞到文件路径

好像我是这样搞到路径滴
2010-07-09 11:05 | vanlin      
发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1755265 aAh38WJYDyE=

导航

公告



=> 稳健 扎实 务实 创新 <=


昵称:JesseZhao
园龄:5年2个月
粉丝:42
关注:28

搜索

 
 

常用链接

我的标签

随笔分类(197)

随笔档案(176)

相册

朋友博客

网站链接

积分与排名

  • 积分 - 338302
  • 排名 - 203

最新评论

阅读排行榜

评论排行榜

推荐排行榜