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

  • 相关阅读:
    js递归优化
    音视频混流
    JS的发布订阅模式
    redhat7.4 docker run启动容器报错container_linux.go:449
    使用Docker部署vue的前端应用过程
    Mac下安装pip
    powerDesigner 把name项添加到注释
    SQL SERVER 2012 连接报错
    CentOS minimal 安装图形界面
    SQLServer2008卸载后重装问题
  • 原文地址:https://www.cnblogs.com/millionsmultiplication/p/12718162.html
Copyright © 2011-2022 走看看