VBGood网站全文搜索 Google

搜索VBGood全站网页(全文搜索)

VB爱好者乐园(VBGood)

 找回密码
 立即注册
搜索
查看: 7516|回复: 14

[讨论] 18年来永远的迷!VB中窗口子类化在IDE调试时为什么会导致IDE崩溃?

[复制链接]
发表于 2016-1-18 22:09:47 | 显示全部楼层 |阅读模式

VB中窗口子类化在进入IDE调试时为什么会导致IDE崩溃?

又把N年前的高级VB编程翻出来看看,看了半天不管中文还是原版,这个 mattew 也没把这个问题讲得明白。这个 mattew 水平还行,但这编写文章水平真是一般般。


VB6从1998年出生到现在18年了,我没见着一个人把这个问题讲得透彻的。看来这个问题成永远的迷了!


我理解只能有下面两个层面,还不知道是真还是假。

传说1,进入IDE或进行调试时,导致自定义窗口过程地址无效,自然窗口崩溃。这是真的吗?如果是,那是什么原因导致函数指针无效?
传说2,IDE 时, AdreessOf 获得的地址不是函数代码的地址,实际为VB代理函数的地址,进入IDE后代理地址失效,自然窗口崩溃。
这是真的吗?如果是,为什么VB需要这样做,为什么需要代理函数?
 楼主| 发表于 2016-1-19 14:48:34 | 显示全部楼层
本帖最后由 topses 于 2016-1-19 15:21 编辑

看了好多种子类编写的方法, 在N年前看到VB子类化代码中有"4AE00DBA5700D054D0581....", 我会说:天哪!!!这是大神! 竟然有人在VB中嵌入汇编!
可到今天我会说这人当时还是菜鸟,还在路上。
今天还搜索到竟然有人将子类化中整个模块的重定向模块(函数)全部用这样的机器编写。
如果10年前编写这类代码的人今天还是干着程序员或是与代码相关的工作,他今天应该不会这样写。

当然不可否认我自己是半桶水,而且还是业余的。

几个概念总结:
asm: 汇编语言,最接近机器语言的一种表述
inline asm:内联汇编,或叫线汇编, 或者叫内嵌汇编(台湾译)
machine code: 机器码,由 eip 控制, cpu 来执行(在内存中)的二进制码

误区调整:
1,VB代码中出现的"4AE00DBA5700D054D0581...."这是汇编代码。
      错,这只是用字符串表示的机器码(二进制),它还要则自己的代码翻译成二进制。

2,VB中可执行了"4AE00DBA5700D054D0581...."代码,应该是内联汇编。
      错,VB 中是无法进行内联汇编,C 中关键字为 inline。
      虽然VB执行 但是通过函数代理(function delegator)来执行的,过程如下:
      先要将字符串(保存在堆区)转换为二进制后,并保存在栈区(注意不是堆区),然后再通过回调函数来调用执行。
      即函数代理是通过回调函数实现。
      

3,函数代理它的效率高吗?
      错,由于它是字符串(堆区)它的效率与真正汇编函数不是一个等级,比如VB中调用三条指令的函数:汇编代码编写的函数,最终可能就4条指令。那么通过用函数代理来调用,如果用轻量对象(matthew发明的)则执行的指令可能要400条以上
     如果像一般都是字符串,那么执行指令至少可能要上1千条多指令

4  为什么为字符串会有这么多指令?
     因为一个堆块申请的就有1千来条指令。所以VB中要尽量避免字符串的运算。





回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-19 15:01:46 | 显示全部楼层
7 栈为什么可执行,而堆不可执行
6 为什么栈比堆快?
5 为什么先要将字符串转换为二进制后,还将其保存在栈区,直接在堆区不行吗?
    因为 cpu 只能执行栈区代码(.text 段),而不能执行堆区代码(.data 段),那又为什么呢?
   
    因为有段描述符,它标识了内存中哪些地址CPU可执行,哪些不可执行。为什么要标识?

    因为这里内存是虚拟内存,所以栈肯定在内存中,而堆不一定在内存中,可能在硬盘中。这就回答了为什么有时候栈要比堆快很多的问题。


一个一个字码的。  多多指教
      


回复 支持 反对

使用道具 举报

发表于 2016-1-19 15:03:06 | 显示全部楼层
不知所云
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-19 15:18:13 | 显示全部楼层
本帖最后由 topses 于 2016-1-19 16:16 编辑

所以总结一点:对于 VB 中是无法进行内联汇编,但可以嵌入机器码。当然我们是通过汇编代码在编译器中获得机器码的,一般是通过VC++。
VB中搞机器码这种事情VB最好不要干,要交给会干的人去干,因为维护难、调试难、理解难、执行效率也低。如果你是菜鸟或是闲着蛋痛或是好奇,就干吧(因为这个过程也会学到不少东东,我就是这样干过来的,当然现在还是半桶水)。

对于交给会干的人干,我就是这么干的,
    代理函数:自己用C写一个代理函数的API将其放入自己底层实现的DLL中,当然在TLB中定义好接口。这速度不比通过 WINAPI 如 SetWindowLong....实现,速度不是杠杠的,因为你知道你自己API里面干了什么,而 WINAPI 那是MS 的你知道干了毛(汇编跟踪发现它确实干了很多毛)。
我的代理函数的指令就一条jmp指令(没错 ret 也不要,当然你需要依据参数数量添加不同接口),这就是交给会干的人干的好处。非得一定要在VB中实现吗,像 matthew 用轻量对象, 那是走了一大圈,还效率慢,那不是找死吗。
就像现在好多牛人最初学C入门一两年,后来发现C++能干好多事情,底层可以干、交互面又可以干,要C又有何用,果断放弃C。后来用了10来年的C++,发现C++就是教书先生,花花肠子太多(重载、继承、多态。。。我只是解决问题要这么多理论干毛。。),不实际,又再开始返回用C,再用其他语言来实现交互面。当然不是说C++没用---还是一句话“交给会干的人干”——让2B也能懂——这不是KISS原则吗



回到我自己的问题:其实难点在于,我只能(只会)通过编译后的代码调试,而我无法(关键是不会)对VB调试时进行再调试跟踪,从而无法知道VB的IDE在调试时干了什么,怎么干的
回复 支持 反对

使用道具 举报

发表于 2016-1-20 11:53:01 | 显示全部楼层
你比我好,我到现在还分不清什么是C,什么是C++,什么是VC。
回复 支持 反对

使用道具 举报

发表于 2016-1-20 12:50:38 | 显示全部楼层
个人认为子类化就是消息机制,vb不支持多线程,但消息本身是多线程的。vb过程一旦中断,就会使地址指0,导致程序崩溃。
回复 支持 反对

使用道具 举报

发表于 2016-1-25 10:43:09 | 显示全部楼层
这个问题好几年前就有很详细的解释了。你不知道说明你没仔细看论坛
回复 支持 反对

使用道具 举报

头像被屏蔽
发表于 2016-1-26 23:14:53 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-2-2 09:27:09 | 显示全部楼层
reker 发表于 2016-1-25 10:43
这个问题好几年前就有很详细的解释了。你不知道说明你没仔细看论坛

首先谢谢你的参与,
但我要说的是, 你说的是费话, 应该给个链接吧.
那我可以说微软VB开发小组应该在25年前就知道问题所在了.

由此判定, 你也不清楚了解VB的调试机制. 或者100%你对其也是一知半解.
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

文字版|手机版|小黑屋|VBGood  

GMT+8, 2022-6-30 19:27

VB爱好者乐园(VBGood)
快速回复 返回顶部 返回列表