zoukankan      html  css  js  c++  java
  • C# 中size_t的暗坑

    最近在接SDK,在写DllImport遇到一个神奇的暗坑

    export代码和DLLImport

    #if defined(_WIN32) || defined(_WIN64)
    
    #define __DLLEXPORT__ __declspec(dllexport)
    
    #else
    
    #define __DLLEXPORT__
    
    #endif
    
    extern "C"
    {
    	__DLLEXPORT__
    	void Init(size_t* requiredSize,char* buff)
    	{
    		....
    	}
    
    }
    
     [DllImport("SDK")]
        public static extern void Init(ref int requiredSize);
    

    DLL是64位,测试代码如下

    int a = 1;
    StringBuilder sb = new StringBuilder(1024);
    Init(ref a, sb);
    print(a);print(sb);
    

    结果惊奇的发现sb = NULL

    换了段测试代码

    int a = 1;
    StringBuilder sb1 = new StringBuilder(1024);
    StringBuilder sb2 = new StringBuilder(1024);
    Init(ref a, sb2);
    print(a);print(sb1);print(sb2);
    

    发现sb2的数据是正常的,sb1依旧是NUll

    和同事研究了一下,最后发现是DllImport写得不对

    换成以下写法就正常了

     [DllImport("SDK")]
    public static extern void Init(ref UIntPtr requiredSize);
    

    导致这个bug的原因是因为size_t的跨平台性,C#下于它匹配的数据类型是UIntPtr,同样可以做到32位系统是4字节,64位系统是8字节,而且都是Unsigned Int

    原来的写法之所以会出现异常奇怪的bug是因为c++的方法会将requiredSize置空后再赋值。

    而C#下由于a和sb数据是连续的,2个加起来字节数才能和size_t对等,结果导致了sb也被置空,真是危险的c++

  • 相关阅读:
    终于开通了
    <input>表单元素readonly时光标仍然可见
    关于字体
    SSI架构中get***方法潜在调用
    为uploads文件夹瘦身
    在JSP里使用CKEditor和CKFinder
    centos5.5上搭建svn服务器
    多文件上传
    属性化ATL,DCOM,SIM,IID
    BSTR转换成char*
  • 原文地址:https://www.cnblogs.com/millionsmultiplication/p/12718162.html
Copyright © 2011-2022 走看看