DX10下面WSASocket阻塞的情况

今天帮群友调程序,说是程序会卡在WSASocket这一句。看CallStack

 

大概的流程是这样的

Application.Run –> LoadLibrary(A.dll, 带包bpl)->diocp.socket.utils( 初始化单元) –> loadIocpExFunction->WSASocket(阻塞了)

 

后来在主程序中引用diocp.socket.utils单元,使得初始化WSASocket提前到EXE中完成,一切正常

Eclipse(Ubuntu)中使用git插件

 

1.首先安装Git插件,可以Help –>Eclipse Maketplace搜索Git,进行更新或者安装。

2.安装后可以在Windows –> Show Views->Others… 把Git 仓库显示出来

image

3. 然后可以远程下载一个(Clone a Git respository)

image

Next后, 选择一个本地存放的位置,finish就好,如果第一次使用,会要求输入一个密码,自己设定一个,记住就好

image

后面那个找回密码的自己看着办就好了,反正是本地使用

4.然后可以把仓库中的项目导入到工作项目中 (我怎么觉得是导出来,进行使用。。。)

image

选择怎么操作,我们这里是把git上面的项目导出来使用, 选择的第一个

image

然后会出现仓库中的项目,选择一个进行操作

image

完成后可以看到项目出来了,可以开始写程序了。

image

导入现有项目到仓库中

image

image

然后可以提交了,如果没有设置信息,可以进行设置

image

提交你想要的文件后,就然后可以Push了

image

最后登陆oschina.net上面看到已经上传了

image

Eclipse中使用EGit插件就是这样的过程了。

上面过程在Ubuntu14.04LTS版本下面操作完成。

 

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

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

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

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

[C#-SQLite] SQLite一些奇怪的问题

今天整C#的DAO层,我用的2013, 用的4.0的.NetFramework刚刚创建完Helper就出现异常

+        Connection    “helper.Connection”引发了“System.IO.FileLoadException”类型的异常    System.Data.IDbConnection {System.IO.FileLoadException}

image

 

后来在搜索到一篇文章,在app.config中加入

<startup useLegacyV2RuntimeActivationPolicy=”true”>
<supportedRuntime version=”v4.0″/>
<requiredRuntime version=”v4.0.20506″ />
</startup>

http://blog.163.com/lemon_wangjun/blog/static/1197883802011312104054675/

 

加入后,倒是好了,但是很奇怪,有时候会出现下面这种异常

76H{`0$PJYTQSBQYSB2WFYG

 

后来翻了一下旧的项目设定,加入如下设定,暂时好了。

<startup useLegacyV2RuntimeActivationPolicy=”true”>
  <supportedRuntime version=”v4.0″ sku=”.NETFramework,Version=v4.0″/>
</startup>

[Delphi编译错误]F2084 Internal Error: U2107

看到这个错误真是头痛,这是一个很旧的项目了,想修改下东西,清理下工程一编译出现这个该死的错误,百度了下,也没解决问题。没办法只好编译所有的BPL了。

 

这个项目是带包编译的,而且带了几个自己的包。

点击这行错误时每次都出现在udmShare上面,想想应该是这个文件有问题,然后这个文件又是ShareCentre.bpl中的文件,shareCentre.bpl是被工程带包编译的,找到shareCentre.bpl重新编译,还是不行,后来折腾几下,一查找发现ShareCentre.bpl, dcp都是很早的,清理掉,重新编译,终于OK了。….

【杂谈接口】-Delphi中使用接口的一些注意事项

原则一:

   如果一个接口需要as成其他接口使用, 如果该接口的实例在该过程中可能会被释放,那么最好将 as 的接口用临时变量保存起来, 然后在使用完后及时将临时接口:= nil;

   如果用as成其他接口直接使用时(如  (lvIntf as IOpera).DoSomething() )系统会自动生成临时变量,存放对应的接口,然后在过程退出时,进行接口变量清理时,会触发接口实例的_release方法。如果对应实例的内存块被破坏,就有可能会导致访问违规的异常。

// 下面这段执行时可能会出现AV异常
var
  lvPlugin: IPlugin;
  lvStoProcessor   : IStoProcessor;
begin
  //物料库存_逻辑处理
  lvPlugin := FPluginConsole.CreatePlugin('STOLogic');
  try
    lvPlugin.PrepareForCreate;
    
    with lvPlugin as IStoProcessor do
    begin
      //处理结存
      DoOnHand(pvFormKey, OPERA_UNAPPR);
      CheckNegative(pvFormKey);
    end;
  finally
    lvPlugin.FreePlugin;
    lvPlugin := nil;
  end;

  // 执行库存处理后的其他脚本
  ExecuteAfterScript(pvFormKey, FJsnConfig.O['STO']);

end;



// 这样做是最安全的
var
  lvPlugin: IPlugin;
  lvStoProcessor   : IStoProcessor;
begin
  //物料库存_逻辑处理
  lvPlugin := FPluginConsole.CreatePlugin('STOLogic');
  try
    lvPlugin.PrepareForCreate;
    
    lvStoProcessor := lvPlugin as IStoProcessor;
    //处理结存
    lvStoProcessor.DoOnHand(pvFormKey, OPERA_UNAPPR);
    lvStoProcessor.CheckNegative(pvFormKey);

    lvStoProcessor := nil;
  finally
    lvPlugin.FreePlugin;
    lvPlugin := nil;
  end;

  // 执行库存处理后的其他脚本
  ExecuteAfterScript(pvFormKey, FJsnConfig.O['STO']);
end;

 

 

…. 未完待续

 

 

 

 

 

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

DIOCP官方社区|MyBean官方社区

http://diocp.wedelphi.com/

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

【杂谈接口】接口对象的生命周期-对象所占用的内存块清理

【概述】

相信经常使用接口的朋友们,经常碰到访问违规异常(Access violation),很多情况下无法理解,认为是编译器的Bug,然后去绕开它,不追其根源,把责任推给IDE,推给编译器(其实本人以前也经常这样想)。其实每个异常都是有原因的,碰到这种问题不要绕开,如果目前无法解决,至少要清楚的知道它出现的起因,不放过每一次追根到底的机会。这才是做程序员的应有的心态。(好像有点扯远了…)

 

【问题描述】

今天公司外包模块中,外包人员反应出现一个很奇怪的问题,说模块中无故出现了AV异常。调试果然如此,而且每次都能出现,每次都能出现的异常就好解决,

最初的代码如下:

一个点击按钮事件中包含如下一段代码:

 

begin
  ....
  (TmBeanFrameVars.GetBean('ef_pcy_frmTree'as INormalSelector).executeSelect(lvPass);
  ....
end;

这样程序在退出函数的时候引发了一个AV异常(end;运行之后),这时候一般对接口不了解的都无从下手。也无从下手进行调试。

 

【问题分析】

首先上面这句简单的访问其实会出现接口的临时变量,而这个变量在函数退出的时候会执行清理,因为executeSelect函数中释放了插件的实例,然后清理临时接口变量时会触发接口对象的__release方法。这个时候引发的一个异常。

我改造一下代码,让错误在函数退出之前出现,完整代码如下。

I`VNO]}GF`0}M_PHZR9C2{U

我用两个局部变量,这样改造后,在执行lvIntf := nil的时候就会出现AV错误。

image

我顺便把executeSelect代码贴一下,可以看到这个插件是一个窗体对象实例。在执行这个函数里面会把窗体显示,然后进行了释放,然后退出了函数。

 

大概的原因明白后,我们调整下代码,代码如下:

PFRPD@W3BOX1E[R2B~V[~K9

注意红色部分,选取完后(释放实例后),然后马上清理接口变量,这个时候,其实内存块应该还是完整的(个人推测),所以清理时不会出现访问违规异常。

 

下面我来做个调试证明我的推测

R7$@CSJ6K@)E74)1XGHER@V

看红色框出来部分,两个接口变量在释放完后,和之前的指向的内存块中值是一样的(我只获取了一个值,其实可以进行完整对比),然继续执行。

{8FA%_B][VZU%_SCWT7%V@U

在看看红色部分,这个时候(其实执行玩cdsOrgan.Append就出现了),lvIntf指向的内存块已经被清理了,因为有新的内存申请。所以后面在清理lvIntf := nil的时候出现访问违规错误。

 

好了到了这个时候,我们应该发现引发异常的真正原因了:在清理接口变量时,访问了一块不可预知的内存块,所以导致了访问违规错误。所以请大家在使用接口过程中注意接口的清理工作。

 

*认真阅读会收获更多。

 

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

DIOCP官方社区|MyBean官方社区

http://diocp.wedelphi.com/

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

【杂谈指针】- 指针的移动

刚刚在群里看到一个这样的问题

MonoPixel: PByte;

Inc(Integer(MonoPixel));这个在32位下没问题,为啥64位不能编译呢?

 

咋一看,以为是把里面的值进行累加,后来一想应该是移动一下指针。

对于这种移动指针的做法有两个错误:

第一个是用了Integer,来转换指针如果在32位下面显然是没有问题的,但是如果是64位,指针是64位,显然再用Integer是错误的。

第二个转换成Ineger后加一,那就相当于整数值 + 1,在PByte时没有问题,因为Byte也是一个字节。但是如果是PInteger指针就会出现错误。

 

我们来看下代码:

如果是PInteger下面应该怎么样做:

var
  p, d:PInteger;
  x : array [0..10] of Integer;
begin
  x[5] := 120;
  p := @x;
  d := p;
  Inc(d, 5);

 

 

首先所有的指针都是一个整数值

image

可以看到如果用inc移动指针,并且会按照指针的类型进行累加,上面PInteger类型Inc后是增加的SizeOf(Integer)。指向数组的下一个元素。

如果单纯的转换成整数来 + 1会 指针的值就是$12EA75显然不是指向下一个元素。当然你取到的值也是错误的。如下面的图

image

显然d^不是我们想要的数据。

除了用inc,也可以这样做,下面的做法也是正确的。

image

请操作指针的朋友们注意啦。

*以上代码在XE6下面测试运行

 

*注意没有IntPtr类型的可以自己定义下类型

type

   IntPtr = cardinal

 

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

DIOCP官方社区|MyBean官方社区

http://diocp.wedelphi.com/

VirtualBox与VMWare网络冲突

VirtualBox安装一个XP后,发现老是上不到网,怎么折腾都不行,

后来发现设备管理器中 vmware accelerated amd pcnet adapter #2显示黄色感叹号

不对呀,这是VirtualBox怎么是vmware的东西,后来百度后,发现禁用vmware网卡,

image

也把VirutalBox 的网卡去掉了vmware bridage Protocol ,重启N次,里面还是那个vm的网卡,

后来百度这个词(vmware accelerated amd pcnet adapter)发现了这篇文章

http://vbox.blogcn.com/6

 

前几日分享了Virtualbox快照备份恢复系统的方法,但是发现从备份中恢复的系统似乎有很多问题,比如经常出现.DLL错误,出现mysql无法启动等问题,搞来搞去,真的很麻烦~~~

搞的都无语了~~

因为网速不给力,所以就在晚上重新下载了个XP ISO,还是雨林木风的~~今天安装好了之后发现,又出现vmware accelerated amd pcnet adapter显示黄色感叹号,真的是没有一件顺利的事情~~NND.

找了好多驱动没弄好,最后一不小心被我发现了解决的办法~~

在更新网卡驱动的地方右键--然后选择更新驱动,然后选择不搜索,自己安装,然后选择AMD的那个网卡即可,这样就能正常上网了,有浪费了我半个多小时,哎,我就想好好用下虚拟机,有这么困难么~~~真的搞的没办法~~~

终于搞定了

虚拟机的网络设定

image

关于SimpleMsgPack中swap引发的问题大端法和小端法研究笔记

今天diocp裙中[珠海]-芒果反应了一个关于SimpleMsgPack的问题

msgPack.AsFloat = 2.507182;

经过编码再解码后,会直接触发异常。

 

因为msgPack的标准,在打包的数据是大端法IEEE 754

下面是msgPack的标准说明

Float format family stores a floating point number in 5 bytes or 9 bytes.
float 32 stores a floating point number in IEEE 754 single precision floating point number format:
+--------+--------+--------+--------+--------+
|  0xca  |XXXXXXXX|XXXXXXXX|XXXXXXXX|XXXXXXXX
+--------+--------+--------+--------+--------+

float 64 stores a floating point number in IEEE 754 double precision floating point number format:
+--------+--------+--------+--------+--------+--------+--------+--------+--------+
|  0xcb  |YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|
+--------+--------+--------+--------+--------+--------+--------+--------+--------+
where
* XXXXXXXX_XXXXXXXX_XXXXXXXX_XXXXXXXX is a big-endian IEEE 754 single precision floating point number
* YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY is a big-endian
  IEEE 754 double precision floating point number

 

小端法变大端法把自己顺序调整下就好了

在SimpleMsgPack中有一个这样的函数,可以对Double类型的数据进行交换字节数。

procedure swap64Ex(const v; out outVal);
begin
  // 7F F5 B8 6F B5 0E 04 40

  // 40 04 0E B5 6F B8 F5 7F
  PByte(@outVal)^ := PByte(IntPtr(@v) + 7)^;
  PByte(IntPtr(@outVal) + 1)^ := PByte(IntPtr(@v) + 6)^;
  PByte(IntPtr(@outVal) + 2)^ := PByte(IntPtr(@v) + 5)^;
  PByte(IntPtr(@outVal) + 3)^ := PByte(IntPtr(@v) + 4)^;
  PByte(IntPtr(@outVal) + 4)^ := PByte(IntPtr(@v) + 3)^;
  PByte(IntPtr(@outVal) + 5)^ := PByte(IntPtr(@v) + 2)^;
  PByte(IntPtr(@outVal) + 6)^ := PByte(IntPtr(@v) + 1)^;
  PByte(IntPtr(@outVal) + 7)^ := PByte(@v)^;
end;

然后我重载了一些函数 这个函数对传入的Double进行交换字节然后返回Double类型

function swap(v:Double): Double; overload;
begin
  swap64Ex(v, Result);
end;

 

上面这个浮点数据 2.507182,经过交换后 如果仍然用Double类型来存放会是一个NaN, 会触发一个无效的浮点型数据的异常。因为不符合小端法的IEEE规则。

经过稍微修改后正常

function swap(v:Double): Int64; overload;
begin
  swap64Ex(v, Result);
end;

返回的值用Int64来存放这样就好了。

 

注意不要把一个不是Double类型的数据直接强制转换成Double类型,因为Double是有标准字节格式的,当然Single一样。

 

感谢,qdac-swish, 小白一起帮忙验证推理。