• 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++

  • 相关阅读:
    String的equals和hashCode方法
    查看oracle中表的索引
    初识RESTful
    linux安装字体库(simSun为例)
    排序之快排(JS)
    面向对象的三个基本特征 和 五种设计原则
    排序之希尔排序(JS)
    关于正则表达式
    Oracle 表分区介绍与使用
    一个复杂关联的sql
  • 原文地址:https://www.cnblogs.com/millionsmultiplication/p/12718162.html
Copyright © 2020-2023  润新知