当前位置: 首页 > wzjs >正文

武汉关键词排名提升搜索引擎优化趋势

武汉关键词排名提升,搜索引擎优化趋势,惠州seo计费管理,扫二维码直接进入网站怎么做函数直接返回bool值和返回bool变量差异 背景 在工作中遇到一个比较诡异的问题,场景是给业务方提供的SDK有一个获取状态的函数GetStatus,函数的返回值类型是bool,在测试过程中发现,SDK返回的是false,但是业务方拿到的…

函数直接返回bool值和返回bool变量差异

背景

在工作中遇到一个比较诡异的问题,场景是给业务方提供的SDK有一个获取状态的函数GetStatus,函数的返回值类型是bool,在测试过程中发现,SDK返回的是false,但是业务方拿到的返回值是true。SDK是C语言和C++语言编写的,C语言编写接口层, C++语言编写实际逻辑,业务方是unity,使用C#语言,通过DllImport引用SDK DLL

  • DllImport声明如下
[DllImport("SDK.dll", EntryPoint="GetStatus", CharSet=CharSet.Ansi, 
CallingConventin=CallingConvention.Cdec1)]
public static extern bool GetStatus([MarshalAs(UnmanagedType.LPStr)] string key);
  • C语言接口层
// 声明
__declspec(dllexport) bool GetStatus(const char* key); 
// 定义
bool GetStatus(const char *key)
{return cpp_instance->GetStatus(key);
}
  • C++实现
    C++ 将key对应的状态保存到一个map中,key类型为std::string,值为std::any
template<class typename T>
T GetStatus(const std::string &key)
{if(!status_map_.count(key)) {return {};}const auto &value = status_map_.at(key);if(!value.has_value()) {return {};}try {return std::any_cast<T>(value);} catch (const std::exception &e) {return {};}
}

排查

C++侧排查

通过 SDK的 unity demo 调试未能复现问题,将SDK Attach到业务进程调试问题复现,由于代码中没有中间变量保留结果,都是直接将结果返回。调试不方便。在代码中增加了一行日志打印。结果问题不复现了。

  • 增加一行日志后的代码
bool GetStatus(const char *key)
{auto ret = cpp_instance->GetStatus(key);std::cout << "get status result " << ret << std::endl;return ret;
}

百思不得其解,决定反汇编调试看下,看下增加日志前和增加日志后的汇编代码。
为了方便调试和说明,这里编写了复现的简单demo,如下:

#include <iostream>typedef int (*GetBoolFuncPtr)();static bool GetBool1()
{return {};
}
static bool GetBool2()
{/*  bool ret = GetBool1();std::cout << "ret:" << ret << std::endl;return ret;*/return GetBool1();
}int main()
{/*GetBoolFuncPtr booll = reinterpret_cast<int (*)()>(GetBool1);GetBoolFuncPtr bool2 = reinterpret_cast<int (*)()>(GetBool2);std::cout << booll() << " " << bool2() << std::endl;*/std::cout << GetBool2() << std::endl;int input;std::cin >> input;return 0;
}
未增加日志打印的反汇编代码如下

未增加日志的反汇编代码
可以看到GetBool2()函数中直接返回了GetBool1()函数的结果,return {}的反汇编代码为xor al,alal表示RAX寄存的低8位, 而函数的返回值就是保存在RAX寄存中,所以对于返回值是boolC++函数,直接return {}是将RAX寄存器的低8位清零,RAX的其他位数是残值。之所以只清零低8位是因为在C++中bool 占1个字节。

增加日志的输出代码
static bool GetBool2()
{bool ret = GetBool1();std::cout << "ret:" << ret << std::endl;return ret;
}

反汇编代码
增加日志的反汇编代码
可以看到GetBool2()函数中通过一个中间变量ret保存了GetBool1()的返回值,并且打印ret的值,然后将ret返回,通过反汇编代码可以看到move byte ptr [ret], alGetBool1()的保存在al的值保存在了ret指向的地址,return ret对应的反汇编代码movezx eax, byte ptr [ret]ret的值保存到 eax寄存器,eax寄存器是RAX寄存器的低32位。这里的重点是movezx指令,movezx指令可以将较小的值用0扩展到较大的值。所以这里eax的高24位被清零。

C++侧排查总结
  • return {}返回bool值将清零RAX寄存器的低8位
  • return ret 返回bool值将清零RAX寄存器的低32位
    可以看到 增加了一行日志和没有这行日志的差别在于会清零返回值寄存器RAX的多少位。这个差别为什么会导致unity 拿到的结果不一样呢?需要继续排查。
unity排查
现状
  • 业务unity应用出现问题

  • SDK unity demo正常
    通过和业务开发沟通发现,业务unity应用后端使用的是il2cpp模式,而SDK unity demo则使用的是mono模式,也许是这里出现了问题,果然将unity demo的后端改成il2cpp模式后复现问题。

    那为什么在il2cpp模式下有问题呢?

    il2cpp模式会将C#代码转换成cpp代码,业务同学说在C#的DllImport地方增加解决了

    [return: MarshalAs(UnmanagedType.I1)]
    

    为什么增加这行代码就可以了,原来在C#中的UnmanagedType类型中bool变量是占4个字节,而使用il2cpp模式后C#的代码会被转换成C++代码。Dllimport的代码会转换成类似下面的逻辑(这里只摘出了重要代码)

    typedef  int32_t (CDECL * PInvokeFunc)(char*);
    static PInvokeFunc  il2cppPInvokeFunc;
    if(il2cppPInvokeFunc == NULL) {il2cppPInvokeFunc  = il2cpp_codegen_resolve_pinvoke<PInvokeFunc>(IL2CPP_NATIVE_STRING("SDK.dll"), "GetStatus", ....);
    }
    
结论

从转换后的代码可以看到,il2cpp C++代码解析的GetStatus函数的返回值是int32_t,也就是说SDK内部返回bool的函数,这里被解析成int32_t了,返回int32_t会从返回值寄存器RAX中读取低32位,结合前面的C++demo分析可以解释了为什么没有打印日志拿到的返回值大概率是true,因为没有打印日志,返回 false只清零了RAX寄存器的低8位,而il2cpp中读取了32位,RAX寄存器大概率有其他函数调用的残值,导致il2cpp中读取到的值大概率为true。而打印了日志,返回false清零RAX寄存器的低32位, il2cpp代码读取正确

参考

https://stackoverflow.com/questions/20035826/why-dllimport-for-c-bool-as-unmanagedtype-i1-throws-but-as-byte-it-works
https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.unmanagedtype?view=net-9.0

http://www.dtcms.com/wzjs/161279.html

相关文章:

  • 网页游戏网站开发人工智能培训机构排名
  • 切实加强政府门户网站建设网络seo是什么意思
  • 手机app开发网站模板资源优化网站排名
  • 长春精神文明建设网站百度商业账号登录
  • 冀州网站制作公众号关键词排名优化
  • 大型网站 div百度网盘app官网下载
  • 创个网站怎么弄全网搜索
  • 人才招聘网站建设方案深圳推广不动产可视化查询
  • 商城类网站如何众筹品牌推广经典案例
  • 天津市建设工程交易管理网站东营网站建设制作
  • wordpress 做大型网站吗google play官网
  • 厦门 微网站制作百度推广账户优化方案
  • 昆山做网站多少钱湖南seo优化排名
  • 做招聘网站的客户想退钱知了seo
  • 南宁网站定制google开户
  • 网站建设网站建设清理大师
  • 编程网站项目做哪个比较好成都网站建设软件
  • 家具网页设计素材搜狗seo快速排名公司
  • 养殖场在哪个网站做环评备案环球网疫情最新
  • 宁波设计网站公司公司官网制作多少钱
  • 网站推广托管公司今日刚刚发生的军事新闻
  • 菏泽做网站电话html简单网页成品
  • 怎样做instergram网站营销中国企业100强
  • 网站建设发布教程视频教程深圳网站设计实力乐云seo
  • 外包公司的人好跳槽吗seo的研究对象
  • 重庆最新新闻事件今天seo的含义
  • 网站维护案百度指数查询app
  • access 数据库做网站企业网络
  • 品牌推广全案宁波核心关键词seo收费
  • 快速达建网站公司网站建设全包