【MyBean调试笔记】接口的使用和清理二(关于接口在MyBean中的应用注意)

【DEMO信息】

有问题的DEMO, 由【[北京]火鸟】提交

【问题描述】

程序关闭时出现AV错误

JEGJM3O3N445M38LK{JWTX0

【问题解答】

1:你有一个TDataMoudle的单实例插件,GetBean后他的Owner是vclOwners。在退出程序时清理了VclOwners后,然后清理单实例的接口为nil时出现了AV错误, 因为单实例要保留一份接口, 一般情况是不会出现av的
     这里mybean可以优化下,先清理单实例的接口, 但是也不能保证,如果插件在其他DLL时会出现的情况

2:第二个问题是主窗体上面声明了很多插件的实例接口, 如果不提前Free主窗体, 系统关闭主窗体的时候,Delphi会在清理对象的时候会自动清理接口:   接口:= nil, 这样我们都知道 会触发实例的release方法, 但是这个实例已经被释放了,而那块内存可能被破坏。所以主窗体先释放,避免提前清理接口

     (插件接口如果是由TComponent类已经他的子类实现, 可以在对象的Destroy时手动清理变量Pointer(AComponentIntf) := nil;  这样不会触发release方法。如果是接口管理生命周期的对象请不要这样做)

这也是我越来越讨厌Delphi自动编译add/release方法的原因了, 虽然component的release方法都基本没什么用, 但是如果这个实例对应的内存地址已经被破坏, 再去访问relase对应的那块地址时可能会参数AV

 

出现问题的原理就是我刚刚说的哪两种情况
归根到底还是接口赋值为nil的时候,触发了一块无效的对象空间的relase方法

 

 

【建议使用规范】

1. 窗体除非特殊的情况, 一般不要注册单实例,在关闭后,最好去释放窗体, 比如Action := caFree。

2. 主窗体提前释放,然后清理插件。推荐写法:

image

3. 单实例一般建议用由接口管理对象生命周期插件(继承TInterfacedObject)。而非TCompnent类级子类对象。

VS2013使用rtklib中需要注意的一些问题(编译)

最近因为项目需要需要对rtcm数据进行解码,rtklib提供了很多底层的函数,准备直接输出标准DLL的方式供C#调用。下面把项目中引用rtklib源码需要注意的地方记录下。

1. 首先在vs2013中新建一个win32的dll项目

2. 在项目上添加一个文件夹[rtklibsrc]然后在文件夹上【添加现有项目】把rtklib的源文件加入工程。在rtklibsrc下建立rcv把rcv下面的文件也添加到工程

  image

3. 现在开始编译工程,你会发现很多错误。下面我们一步步来解决错误。

   1>  Q: error C1853: “Debug\rtklibHelper.pch”预编译头文件来自编译器的早期版本,或者预编译头为 C++ 而在 C 中使用它(或相反)    x:\xxxx\rtklibhelper\rtklibsrc\tle.c    1    1    rtklibHelper
          A: 不使用预编译头image

         

  2> Q: 错误    1    error C4996: ‘strncpy’: This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.    x:\xxxx\rtklibhelper\rtklibhelper\rtklibsrc\tle.c

        A: 其实提示上面已经告诉你方法了,需要你加入预编译指令来取消这个错误[_CRT_SECURE_NO_WARNINGS]

         image

 

3> Q:  error C4996: ‘gethostbyname’: Use getaddrinfo() or GetAddrInfoW() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings    x:\xxxx\rtklibhelper\rtklibsrc\stream.c

      A: 这个错误和上面类似,加入[_WINSOCK_DEPRECATED_NO_WARNINGS ]

 

4> Q:接下来是一个这样的错误  error C2466: 不能分配常量大小为 0 的数组    x:\xxxx\rtklibhelper\rtklibsrc\rinex.c

image

    A:这个错误我们来看一下, 在[MAXPRNGLO]上面按F12,看他的定义处

        image 这个常量为0,那么不能进行编译,我们想上面一样在预编译器里面加入 ENAGLO

 

5> Q:  error C1083: 无法打开包括文件: “rtklib.h”: No such file or directory    x:\xxxx\rtklibhelper\rtklibsrc\rcv\ublox.c    41    1    rtklibHelper

      A:  添加附加目录设置[.\rtklibsrc] image, 注意是C/C++的常规下面,不是链接器的常规页面。

 

6> Q:  error LNK2005: _input_oem3 已经在 novatel.obj 中定义    x:\xxxx\rtklibhelper\novatel_old.obj    rtklibHelper

      A: 这个错误是添加文件的时候添加重复了novatel_old.c不应该添加了,删除即可

          image 

 

  7>:  Q:  error LNK2019: 无法解析的外部符号 _settspan,该符号在函数 _postpos 中被引用    x:\xxxx\rtklibhelper\postpos.obj    rtklibHelper

                error LNK2019: 无法解析的外部符号 __imp__timeGetTime@0,该符号在函数 _tickget 中被引用   x:\xxxx\rtklibhelper\rtkcmn.obj    rtklibHelper

                error LNK2019: 无法解析的外部符号 __imp__accept@12,该符号在函数 _accept_nb 中被引用    x:\xxxx\rtklibhelper\stream.obj    rtklibHelper

        A: 添加附加库[连接器->输入->附加依赖库]添加winmm.lib, ws2_32.lib

         image

    

  8>:Q: error LNK2019: 无法解析的外部符号 _showmsg,该符号在函数 _convrnx 中被引用    x:\xxxx\rtklibhelper\convrnx.obj    rtklibHelper

        A: 一查showmsg这个函数如果在DLL中需要自己定义,rtklib里面已经做好了处理需要在预处理器里面加入[DLL]即可。

 

预处理器里面我们添加了

_CRT_SECURE_NO_WARNINGS
_WINSOCK_DEPRECATED_NO_WARNINGS
ENAGLO
DLL

 

  image

 

最后rtklibHelper编译成功了,可以开始编写具体的功能函数了。

 

 

=========================================================================================

diocp|mybean官方网站: 主域名: www.diocp.org

diocp|mybean官方论坛: http://delphi.net.cn