[瓶颈] 从SafeArray无法销毁 到 ocx生成

1 经过:
遇到问题:SafeArray无法销毁.

通过测试,SafeArrayUnacess和SafeArrayDestroy的返回值,断定问题出现在SafeArrayDestroy。

上网搜索。网上有篇文章引用MSDN,说, SafeArray销毁的时候, 如果数组中的元素已经销毁了. 则会出现崩溃.
仔细的检查,我这边应该不存在这样的问题。

  反复的增加, 删除控件xxx.odl, xxxidl.h文件中新增的接口类型中的字段.
  反复的增加, 删除客户端xxx.tlh文件中新增的接口类型中的字段.
  反复的编译, 测试.
  发现, 如果xxxidl.h  xxx.tlh文件中的字段数一致. 只要不destroy就可以执行.
但,不想把这个内存泄露就这样放过。

  在多次试验后,  发现无论怎样, 读相关数据的时候都有问题. 
  于是怀疑是传入的数据结构和解析使用的数据结构不一致导致的.

  果然通过, IRecordInfo.GetSize() sizeof(yyy)得到大小不一致. 仔细审查两者使用的结构, 发现IRecordInfo.GetSize() 比 sizeof(yyy) 小了8个字节.
   心想, 怎么就少了8个字节了. 突然想起了结构体的字节对齐问题. 然后使用#program pack(4) 使二者一致了.
   但又想,应该验证下控件中的结构体和IRecordInfo.GetSize()是否一致。结论也是不一致. 这才意识到, 不是字节对齐的问题. 应该是没有增加字段成功.
  
   然后查看 tlb文件, 生成tlb文件中有新增的字段. 再次失去了线索.
   虽然知道工程属性最后到会体现在预编译头命令和其他的Alt+F7的设置中。
   但还是对工程属性起了怀疑.  于是自己新建了个简单的工程. 新建的工程是可以的.
   然后查注册表, 注册表中只记录了简单的typeid 和 存储路径. 注册表中是不能存储类型信息的.

   然后向同事求教, 同事使用OLEView查看了控件内容. 发现控件里确实是没有增加成功. 现在知道了tlb信息是存储在ocx文件中的.
   那是什么导致没有增加成功呢?  如果是工程属性的问题, 为什么我第一次可以增加成功了呢. 应该是链接的问题.

       最后, 发现在工程根目录下有一个tlb文件.  应该是最初某个编译版本留下的, 删除之, 重新编译. OK.

  还发现编译的xxx.odl文件的时候, 没有改变xxxidl.h.

  2 结论:
        ocx包含了错误的tlb内容。导致,SafeArray创建的时候,使用的record类型与实际的record类型不一致。
  最终导致了控件和客户端交互的时候对SafeArray指向内存的操作出现问题。由于实际的record比使用的record类型占的内存要大。
  所以写的时候已经出现了内存越界的问题。
  而SafeArrayDestroy的时候,由于结构不一致,推测释放结构中BSTR的时候出现了内存的错位读,导致了数据的异常。

  3 收获: 
odl文件(idl文件),MIDL只需要生成一个tlb文件就可以了.
   VC6默认是不生成头文件 和 UUID文件的. 在odl文件的setting中,可以增加output header file 和uuid file来设置. 
  ocx文件,包含了tlb文件.
   在odl文件中定义的类型(UDT),都有对应的TypeInfo. 这个typeInfo也是存储在tlb中的. 
  GetRecordInfoFromGUID 指定了类型库的ID 通过,类型库ID查注册表,可以找到ocx文件存储目录. 然后就可以获取tlb的信息了. 
 
4 其它:
  ActiveX 工程的编译:
/nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /Fp"Debug/test.pch" /Yu"stdafx.h" /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
  Link选项
  /nologo /subsystem:windows /dll /incremental:yes /pdb:"Debug/test.pdb" /debug /machine:I386 /def:"./test.def" /out:"Debug/test.ocx" /implib:"Debug/test.lib" /pdbtype:sept

  可以看到并么有link tlb,不知道是怎么整合进去的。

5 补充(2008-2-29)
导致安全数组释放错误
1 record信息不正确(记录占据空间不一致,容易导致内存误用)
     控件和调用者 约定不一致
    使用了错误的record GUID

2 先释放了空间
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值