| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 945 人关注过本帖
标题:把函数调用改为直接执行其代码,为何导致不能调试?
只看楼主 加入收藏
tm1mc2
Rank: 2
等 级:论坛游民
帖 子:28
专家分:46
注 册:2014-8-21
结帖率:50%
收藏
已结贴  问题点数:20 回复次数:11 
把函数调用改为直接执行其代码,为何导致不能调试?
我把别人的一个能够正常调试的Dll程序拿来修改。只修改一项:取消一个函数的调用。不调用了,直接执行其代码。
这个函数叫做RegisterIMEClass,它的功能是注册四个窗口类并建立4个窗口。
由于整个程序(由多文件组成)只有一个地方调用此函数,因此我觉得没有必要采用调用函数的方式,就把函数里的程序段直接代替原来的调用函数语句。
调用此函数的语句在Dll程序的入口函数DllMain的开头,见下图中划红线的语句:
图片附件: 游客没有浏览图片的权限,请 登录注册

被调用的函数参见下图:
图片附件: 游客没有浏览图片的权限,请 登录注册

取消调用方式了,就把该程序段中的形参hInstance都用实参g_hInst取代。
此外也取消函数申明。
原函数中的第一句(划红线的那句)“WNDCLASSEX wc;”定义了一个结构变量。
按规定,C语言的变量定义要放在函数开头,或者放到所有函数的前面作为全局变量。因此我把这条语句上移。
结果程序变成这样:
图片附件: 游客没有浏览图片的权限,请 登录注册

这个程序是个汉字输入方法,是个Dll,需要有个调用它的应用程序,一般选择记事本程序NOTEPAD.EXE来调试输入法Dll。
调试那个别人的程序时很正常:按F5以后记事本窗口跳出,选择此输入法后记事本窗口隐退,VC++回到前台,程序就从DllMain进入,到断点停下。
可是我这个改动后的程序,选择输入法后记事本仍然占据前台不肯隐退。这时按字母键的话,字母就出现在记事本上。这样就就无法调试。

想调试的朋友,到此下载程序:
http://www.
下载其中的“初中阶段示范程序”、拼音码表
如果你的系统是XP,就把下载的词库文件py.txt拷贝到:\WINDOWS\system32
建一个文件夹,把初中阶段示范程序《输入法编程入门标准程序.rar 》拷进去双击它,会释放出很多文件和文件夹。把其中的文件夹“说明”中的imm.h覆盖你的VC++的旧版本。
然后进入:Build->set Active Configuration,选中:srf-Win32 Release 。
然后选noteped.exe来调试本Dll。
做法是:
    Project->Settings->Debug->Executable for debug session
单击它下面右边的按钮,点击Browse...。对于windowsXP系统,它在C:\WINDOWS\NOTEPAD.EXE
设置好断点后,点击F5,VC就会打开记事本,在Windows的状态栏中选择“天下无敌”输入法,就可以像调试普通可执行程序一样调试这个输入法了。

[ 本帖最后由 tm1mc2 于 2014-9-28 11:20 编辑 ]
2014-09-28 11:03
天使梦魔
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:37
帖 子:564
专家分:2754
注 册:2007-8-29
收藏
得分:0 
不太想下,结果给出的代码实在没什么,一看链接居然注册。

这样说吧
WNDCLAS是用于声明窗口方式,你自己填信息,其中.hInstance成员是窗口编号,这是最重要的
设置完成后RegisterClass函数用于注册,等于调整信息。
最后CreateWindow调用这个已经注册的编号,它会返回一个句柄。(每个窗口独立句柄)
再然后ShowWindow调用这个句柄显示窗口,你需要UpdateWindow函数刷新这个句柄。
这是整个创建窗口流程,这些函数有EX版本的。


你检查下哪里有问题吧
2014-09-28 22:05
tm1mc2
Rank: 2
等 级:论坛游民
帖 子:28
专家分:46
注 册:2014-8-21
收藏
得分:0 
现在把问题简化:只在路路通的程序中加一句废话(图中红线所示),结果也能造成不能调试。然后把这句废话删除,又能正常调试。
是不是因为我在加入一句后漏了该做的一点事情?
我在加进这句话之后做的事是:存盘、编译、链接、全部链接、按F5。我还需要做啥?
图片附件: 游客没有浏览图片的权限,请 登录注册
2014-09-29 17:38
tm1mc2
Rank: 2
等 级:论坛游民
帖 子:28
专家分:46
注 册:2014-8-21
收藏
得分:0 
把这句话改成g_hInst=hInstDLL;也不行。
把这句话改成hInstDLL=hInstDLL;也不行。
改成只有一个分号的空语句(连同后面的注释)倒是可以的。
2014-09-29 18:01
天使梦魔
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:37
帖 子:564
专家分:2754
注 册:2007-8-29
收藏
得分:0 
说了看下核心进程的书了,顺序顺序<windows核心编程>
dll顺序,你的4个窗口是独立线程吗?
DLL_THREAD_ATTACH是自身创建的时候不运行,而往后任何一个新线程创建就会直接跳到这里,而忽略掉上面
switch的运行顺序知道吧,假如是新线程状态dllmain返回DLL_THREAD_ATTACH从而直接跳过上面.如果你的窗口是独立线程的话那么悲剧了.
<windows核心编程>里同样提到这个问题,而且作者也想过解决方案,但即便是更换方位也不能解决.原话这样:
通过进一步的研究,我终于发现了问题。当进程被创建时,系统也创建一个互斥对象。每
个进程都有它自己的互斥对象,也就是说多个进程并不共享互斥对象。当线程调用映射到进程
的地址空间中的D L L的D l l M a i n函数时,这个互斥对象负责对进程的所有线程实施同步


我不知道你是如何调试的,方式又是怎么样,不过我想到的暂时是这样.
另外,回到我最早之前对你说的,想要学就学原理,光是这样乱调试,出问题也是换汤不换药
2014-09-29 20:18
tm1mc2
Rank: 2
等 级:论坛游民
帖 子:28
专家分:46
注 册:2014-8-21
收藏
得分:0 
谢谢回答。
我去网上书店买了<windows核心编程>,并且到百度文库下载了该书的第19-21,讲动态链接库的部分。
    目前问题是这样:我把别人能够正常调试的程序拿来修改。4个窗口是他的不是我的,我没改,如果他的是独立线程那么我的就是,反之也然。能否正常调试跟是否独立线程无关。不过从我的水平上理解,这4个窗口不是线程。这4个窗口中1个是其余3个的父窗口。它们各有自己的消息处理程序。不过扯这些没用。反正他的能正常调试。
    我只是把一个函数改为直接执行,省去调用环节而已,这几个窗口一点都没改。DLL_THREAD_ATTACH消息的处理也没改。如果我的程序是因为“新线程状态dllmain返回DLL_THREAD_ATTACH从而直接跳过上面.”,那么他的程序为什么就不会“从而直接跳过上面.”?就不会“悲剧了”?
    问题应该出在我跟他的不同点上。但原先修改太多,不同点也太多,因此简化修改:只加一句无错的废话:https://bbs.bccn.net/thread-436751-1-1.html
    结果也不行。所以你上面说的哪些原因不对。那些原因在原来能调试的程序中都有,却能正常调试。
2014-09-30 16:25
天使梦魔
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:37
帖 子:564
专家分:2754
注 册:2007-8-29
收藏
得分:0 
为什么自己就不能做测试。
如果是全局变量的问题就把变量放到那个状态下,反正离开switch时就过期了。
调试的时候中断值呢?返回什么?在等待什么?是单纯的调试等待参数还是编译不过去?
内部代码是否有调试专用的debug宏?

我倒是蛮好奇,对于说的这种改动,不知能否发两份代码一份没问题的原版,一份你只改了一点点的改动版。这个论坛可以上传压缩文件
2014-09-30 19:58
tm1mc2
Rank: 2
等 级:论坛游民
帖 子:28
专家分:46
注 册:2014-8-21
收藏
得分:0 
请教如何把文件传给你?
2014-09-30 20:03
天使梦魔
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:37
帖 子:564
专家分:2754
注 册:2007-8-29
收藏
得分:0 
发帖有上传附件
2014-09-30 20:33
tm1mc2
Rank: 2
等 级:论坛游民
帖 子:28
专家分:46
注 册:2014-8-21
收藏
得分:0 
路路通的软件包:
输入法编程入门标准程序.rar (219.5 KB)

路路通的码表:
PY.zip (460.09 KB)


如果你的系统是XP,就把下载的词库文件py.txt拷贝到:\WINDOWS\system32。这件事最重要,否则程序运行时找不到码表会死机,甚至可能要重装系统
建一个文件夹,软件包拷进去双击它,会释放出很多文件和文件夹。把其中的文件夹“说明”中的imm.h覆盖你的VC++的旧版本中的同名文件。
然后进入:Build->set Active Configuration,选中:srf-Win32 Debug。
然后选noteped.exe来调试本Dll。
做法是:
Project->Settings->Debug->Executable for debug session
单击它下面右边的按钮,点击Browse...。对于windowsXP系统,它在C:\WINDOWS\NOTEPAD.EXE
设置好断点后,点击F5,VC就会打开记事本,在Windows的状态栏中选择你的输入法,就可以像调试普通可执行程序一样调试你的输入法了。

有点眉目了:
其它网站有人这样答复:
如果编译通过,debug是可以进断点的。
不能进断点本身应该是因为源码和实际动态库不一致
你可能有其他的程序加载了这个动态库,这样动态库就不能被替换。
所以,虽然编译通过了但是输入法对应的动态库还是之前的。
当你把代码改回去的时候源码和动态库一致就可以调试了。
实际上输入法对应的动态库从头到尾都没有变。
你可以看一下项目构建的完整输出,发出来好确认问题。还有工程的设置最好也贴一下。

我猜想他的意思是:
我用notepad.exe调试我的程序时,即使关闭那个调试的notpad窗口,或者按shift+F5退出调试,但是电脑上还有其他notepad窗口的话,那么“天下无敌”输入法仍然没有退出,因此下次再调试时系统就不会调用DllMain。

[ 本帖最后由 tm1mc2 于 2014-10-2 11:42 编辑 ]
2014-10-02 11:24
快速回复:把函数调用改为直接执行其代码,为何导致不能调试?
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.019953 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved