iOS问题记录 - Xcode 15安装低版本iOS模拟器(持续更新)
文章目录
- 前言
- 开发环境
- 问题描述
- 问题分析
- 1. 定位问题
- 2. 逆向分析
- 2.1. IDA Free
- 2.2. Hopper Disassembler Demo
- 3. 模拟器日志
- 4. supportedArchs
- 解决方案
- 最后
前言
最近新需求很多,项目改动很大,开发完成后想测一遍在低版本iOS系统上的兼容性,没想到低版本的iOS模拟器设备突然无法创建了。
在去年年底我研究过这个问题,写下了这篇文章iOS问题记录 - Xcode 14安装低版本iOS模拟器(持续更新),虽然当时没有完全解决,但暂时也够用,没想到现在这个问题又出现了。如果还没有阅读过这篇文章,强烈建议先阅读这篇前置文章。
这里先说明一下,虽然标题是Xcode 15安装低版本iOS模拟器,但是在遇到这个问题时Xcode 15还处于Beta版,平时还是以Xcode 14.3.1版本为主,至于标题中为什么用Xcode 15,请继续往下看。
开发环境
- macOS: 13.4
- Xcode: 14.3.1 / 15 beta 5
问题描述
在Xcode 14.3.1版本中,低版本iOS模拟器文件已经修改了Info.plist
文件中的CFBundleIdentifier
属性值,但是创建iOS模拟器的时候却还是无法选择。从官网重新下载Xcode 14.0.1版本创建低版本iOS模拟器,还是无法选择无法创建,最低只能创建iOS 14.0.1模拟器。
问题分析
1. 定位问题
首先怀疑是不是Xcode 14.3.1版本又加了其他限制,导致原先的方法失效。找了一台打包机,将Xcode版本升到14.3.1,尝试创建低版本iOS模拟器,一切正常!这是怎么回事?
这就不得不提CoreSimulator
框架,文件位于/Library/Developer/PrivateFrameworks/CoreSimulator.framework
,Xcode的模拟器管理靠它来实现。现在Xcode版本一致,却出现一个正常一个不正常,难道是CoreSimulator
框架版本不一致?
查看CoreSimulator
框架版本的两种方法:
- 通过命令查看
xcrun simctl --version
执行输出:
@(#)PROGRAM:simctl PROJECT:CoreSimulator-917
simctl
是用于管理和控制模拟器的命令行工具,更多用法可以通过xcrun simctl help
命令查看。
- 通过
version.plist
文件查看
找到CoreSimulator
框架文件(前面有写路径),version.plist
文件位于Versions/A/Resources
目录路径下。
经过对比发现,我电脑上的版本是917
,而打包机上的版本是885.2
。咦🤔?这版本什么️时候升级的我怎么不知道。思来想去,很可能是在前几天体验Xcode 15 beta 5版本的时候更新了CoreSimulator
框架。打开大版本更新的Xcode时,一般都会弹出一个安装界面,然后请求管理员权限安装其他组件:
这时候就会自动更新CoreSimulator
框架,当然也不限于这个框架,还有其他一些组件也会更新。
接下来就是验证是不是因为CoreSimulator
框架版本不一致导致的问题,最简单的验证方法是将917
版本降回885.2
版本,然后再测试能否创建低版本iOS模拟器。我本来打算先将已有的CoreSimulator
框架文件删除,然后从打包机复制一份到原路径,结果刚删除立马就弹出这个:
允许操作后自动重新安装了885.2
版本的CoreSimulator
框架,用Xcode 14.3.1版本实测可以创建iOS 12.0版本的模拟器,同时运行与调试也一切正常。
由此可以确定当前问题是CoreSimulator
框架升级版本后导致的,那么该怎么解决呢?如果是Xcode 14遇到这个问题,直接删除新版本的CoreSimulator
框架然后自动重装老版本即可(如果没有自动重装,重新打开Xcode 14也可以完成安装)。不过,这治标不治本,后面Xcode 15还是无法创建低版本iOS模拟器。
2. 逆向分析
CoreSimulator
框架的核心是Versions/Current/CoreSimulator
可执行文件,想知道框架升级改了什么导致了当前问题的话,逆向分析这个可执行文件是最快的方式。
以下所使用的逆向工具虽然是免费版本,但是如果不开代理可能下载很慢,这里提供分享链接,希望能对你有所帮助。
- 百度网盘
2.1. IDA Free
关于逆向工具,我首选的是IDA Pro的免费版IDA Free,虽然功能受限,但是基本的静态分析是可用的,最重要的是免费。需要特别注意的一点是IDA Free被限制了只能处理x86/x64
架构的二进制文件,这对CoreSimulator
可执行文件不是问题,通过file
命令可以知道这个可执行文件是个Mach-O
通用二进制文件,包含了x86_64
架构。
file /Library/Developer/PrivateFrameworks/CoreSimulator.framework/Versions/A/CoreSimulator
执行输出:
/Library/Developer/PrivateFrameworks/CoreSimulator.framework/Versions/A/CoreSimulator: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit dynamically linked shared library x86_64] [arm64e]
/Library/Developer/PrivateFrameworks/CoreSimulator.framework/Versions/A/CoreSimulator (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64
/Library/Developer/PrivateFrameworks/CoreSimulator.framework/Versions/A/CoreSimulator (for architecture arm64e): Mach-O 64-bit dynamically linked shared library arm64e
建议复制一份CoreSimulator
可执行文件到其他目录用于静态分析,用IDA Free打开时选择x86_64
架构文件:
当底部的消息输出窗口提示初始化自动分析已完成(“The initial autoanalysis has been finished.”)就可以开始进行静态分析。
万事开头难,现在该怎么找到问题所在呢?之前通过修改Info.plist
文件中的CFBundleIdentifier
属性值绕过了Xcode的限制,那说明CoreSimulator
可执行文件很可能内置了各个模拟器版本的CFBundleIdentifier
值用于判断,以此为切入口或许能找到新增加的限制判断。
通过快捷键Shift + Fn + F12
或[菜单栏 View] -> [Open subviews] -> [Strings]打开字符串窗口,然后快捷键Command + F
搜索关键词com.apple.CoreSimulator.SimRuntime.iOS-
:
选择任意一个搜索结果双击来到IDA View窗口,通过快捷键X
查看引用:
结果没什么用,定位不了在哪里被引用。只好换个思路,从可能相关的函数入手。结合函数列表和模拟器文件的名称(iOS xx.x.simruntime
),基本可以确定要找的函数应该和SimRuntime
(模拟器运行时)相关。
从这些函数(方法)名可以看出CoreSimulator
框架应该是用Objective-C
开发的,一般首次加载文件时会弹框提示检测到Objective-C
结构,询问是否要解析并重命名方法,以上的方法名经过了解析处理。看方法命名,严重怀疑-[SimRuntime isAvailableWithError:]
方法就是我们要找的。在IDA View窗口使用快捷键Fn + F5
查看该方法的伪代码:
相对于汇编代码,伪代码可读性确实高了些,方法调用(objc_msgSend
)一目了然。不过一些引用数据,特别是字符串没有直接将指针转为实际指向的内容,例如&off_D9D70
指针,需要点进去才知道指向的内容是arm64
字符串,这导致阅读和搜索(文本搜索快捷键Option + T
)伪代码都不方便。
分析一番,收获不大,尝试分析其他相关的方法,也没能找到问题所在。或许可以换个逆向工具试试?
2.2. Hopper Disassembler Demo
Mach-O
文件的常用逆向工具还有Hopper Disassembler,它的功能会比IDA Pro弱些,但是更易上手使用。Demo版本虽然功能受限,但是基本够用,唯一需要注意的一点是每次打开只能用30分钟,到时间会弹框强制关闭。
打开Hopper Disassembler,点击Try the Demo
开始使用。将需要分析的文件拖进去,会出现弹框:
这里没有被限制只能处理x86/x64
架构的二进制文件,可以任选选择。等待自动分析完成就可以开始静态分析,详细使用教程请参考官方教程。
相比IDA Free的伪代码,这个的可读性确实更高些。不过分析一番还是没能找到问题所在,难道只能暂时搁置了?
3. 模拟器日志
如果能向分析源码一样,随时能打印日志和调试断点,逆向分析就轻松了。对于修改和调试二进制文件,前面的逆向工具也不是不能做,只是比较麻烦,而且这些功能在免费版上基本受限用不了。
正当我考虑要不要暂时搁置问题的时候,灵光一闪,日志可能一直都存在!在静态分析中经常能看到日志打印:
而且日志打印好像也没什么限制,猜测应该是一直在输出:
通常日志会被写入文件系统(.log
扩展名的文件),那这些日志被输出到哪了呢?尝试搜索.log
字符串查找写入文件路径:
%s/Library/Logs/CoreSimulator/CoreSimulator.%s.log
应该就是日志文件的路径,不过这路径前面部分的%s
还不确定。在汇编显示模式下点击指定行,然后点击右键就可以查看相关引用:
日志文件路径被____SimLogASLInit_block_invoke
函数引用了,从伪代码可知路径前面部分的%s
是被环境变量HOME
的值替换了:
执行env
命令打印环境变量可知,HOME
变量的值是用户目录路径,例如/Users/xxx
,所以模拟器日志文件所在目录的完整路径是/Users/xxx/Library/Logs/CoreSimulator
。打开该目录下的CoreSimulator.log
文件,发现一直在打印这样的错误日志:
Aug 9 21:36:53 mac com.apple.CoreSimulator.simctl[30026] <Error>: Error Domain=com.apple.CoreSimulator.SimError Code=401 "Unable to determine supported architectures for runtime (/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 12.4.simruntime)" UserInfo={NSLocalizedDescription=Unable to determine supported architectures for runtime (/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 12.4.simruntime)}
难道这个报错日志是问题的关键?将CoreSimulator
框架版本降为885.2
后,不再打印类似的错误日志。
补充一点:后续通过逆向发现CoreSimulator.log
日志文件实际应该是CoreSimulator
框架下的Versions/A/Resources/bin/simctl
生成的,不过以上报错的关键信息确实来源于CoreSimulator
可执行性文件。
4. supportedArchs
逆向CoreSimulator
可执行文件,搜索关键词Unable to determine supported architectures for runtime
,通过相关引用定位到-[SimRuntime initWithBundle:error:]
方法:
相关伪代码(省略部分):
loc_9658b:rax = [r15 objectForKeyedSubscript:@"supportedArchs"];rax = [rax retain];var_268 = rax;if (rax != 0x0) {...}else {rax = (r14)(@class(NSBundle), @selector(bundleWithIdentifier:), @"com.apple.CoreSimulator");rax = [rax retain];rbx = rax;r15 = @"Unable to determine supported architectures for runtime (%@)";rdx = r15;rcx = r15;rax = (r14)(rax, @selector(localizedStringForKey:value:table:), rdx, rcx, 0x0);rax = [rax retain];r12 = rax;if (rax != 0x0) {r15 = rax;}rax = (r14)(var_218, @selector(bundlePath), rdx, rcx, 0x0);rax = [rax retain];r15 = [(r14)(@class(NSString), @selector(stringWithFormat:), r15, rax, 0x0) retain];[rax release];[r12 release];[rbx release];var_208 = r15;rax = [NSError errorWithSimErrno:0x191 localizedDescription:r15];rax = [rax retain];if (rax != 0x0) {__SimLog(0x3, "-[SimRuntime initWithBundle:error:]", 0x1fa, @"%@", rax, r9, var_3C0);rax = rax;}r14 = var_1E8;r15 = var_1F0;rbx = var_238;if (r14 != 0x0) {rax = objc_retainAutorelease(rax);*r14 = rax;}r12 = 0x0;r14 = var_1C0;}...
逆向885.2
版本的CoreSimulator
可执行文件,对比同个方法的伪代码,这部分判断逻辑确实是新加的。从以上伪代码可知,r15
(根据objectForKeyedSubscript
可以推测应该是NSDictionary
类型)通过supportedArchs
键获取对应值时,因为键不存在所以返回NULL
(也就是0x0
),进而执行else
代码块打印错误日志。那么r15
的值是从哪来的呢?
通过不断溯源查找应该可以找到,不过这个方法的伪代码很长,需要耗费不少时间精力。换个思路,根据报错信息中出现的模拟器文件路径(/Library/.../Runtimes/iOS 12.4.simruntime
)以及发生错误的方法(-[SimRuntime initWithBundle:error:]
),可以大胆猜测错误是在加载模拟器文件初始化SimRuntime
对象时发生的,所以r15
的值很可能源于模拟器文件中的某个配置文件。
搜索关键词plist
查找可能的配置文件:
咦🤔️?这行rax = [r12 pathForResource:@"profile" ofType:@"plist"];
代码获取了profile.plist
文件的完整路径,感觉很有可能就是它。找到iOS 12.4.simruntime
文件,右键显示包内容,然后搜索profile.plist
,搜索结果如下:
打开后确实没找到supportedArchs
属性。另找一个没报错的模拟器文件,打开其中的profile.plist
文件,确实有该属性:
将iOS 12.4.simruntime
文件中的profile.plist
复制一份到其他地方,然后打开添加supportedArchs
属性并保存,最后将修改后的文件替换原来的文件。
重新打开Xcode创建低版本iOS模拟器,还是不行。难道这么做无效?再次检查一下模拟器日志还有没有报错,好吧,原先的错误没了,来了新的错误:
Aug 9 23:28:01 mac com.apple.CoreSimulator.simctl[30026] <Error>: Failed to setup launchHostClient for runtime com.apple.CoreSimulator.SimRuntime.iOS-12-4-1: Error Domain=NSPOSIXErrorDomain Code=88 "Malformed Mach-o file" UserInfo={NSLocalizedDescription=Failed to open liblaunch_sim: dlopen(/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 12.4.simruntime/Contents/Resources/RuntimeRoot/usr/lib/system/host/liblaunch_sim.dylib, 0x0101): tried: '/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 12.4.simruntime/Contents/Resources/RuntimeRoot/usr/lib/system/host/liblaunch_sim.dylib' (fat file, but missing compatible architecture (have 'x86_64,i386', need 'arm64')), '/System/Volumes/Preboot/Cryptexes/OS/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 12.4.simruntime/Contents/Resources/RuntimeRoot/usr/lib/system/host/liblaunch_sim.dylib' (no such file), '/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 12.4.simruntime/Contents/Resources/RuntimeRoot/usr/lib/system/host/liblaunch_sim.dylib' (fat file, but missing compatible architecture (have 'x86_64,i386', need 'arm64')), NSLocalizedFailureReason=Malformed Mach-o file}
关键报错信息:
but missing compatible architecture (have 'x86_64,i386', need 'arm64')
报错信息说的很明白,缺少arm64
架构。这些低版本的模拟器文件肯定是没有arm64
架构的,毕竟发布的时候arm
架构的M系列芯片还没出来。逐一查看电脑上已有的iOS模拟器文件,发现supportedArchs
属性是从iOS 14.0.simruntime
开始出现的,这就对了,iOS 14/Xcode 12/M1芯片都是2020年发布的,也就是说,当前问题只会出现在iOS 14以下。
看来不能完全照搬照抄,将supportedArchs
属性中的arm64
删除,重新打开Xcode创建低版本iOS模拟器,创建成功!不过尝试启动,却出现了弹框报错:
经过实测发现是模拟器相关的服务没有重启。模拟器服务CoreSimulatorService
是CoreSimulator
框架的一部分,用于管理模拟器的创建、启动、停止和删除等功能。打开活动监视器,找到com.apple.CoreSimulator.CoreSimulatorService
进程,然后结束进程。
重新运行iOS 12.4版本的模拟器,能启动但是黑屏。好吧,可用的低版本iOS模拟器又少了。实测iOS 13.7以下版本不是黑屏就是无法运行和调试应用,真是忙了个寂寞!明明Xcode 15的部署目标最低还是iOS 12,却不支持iOS 13.7以下的模拟器。以下来自官方支持文档:
文档中Xcode 14.3.1版本的iOS模拟器显示最低支持iOS 13.7,但实际可下载列表中最低版本已经是iOS 14.0.1。
解决方案
强烈建议先阅读前置文章iOS问题记录 - Xcode 14安装低版本iOS模拟器(持续更新),然后在修改Info.plist
文件的基础上,再额外修改模拟器文件中的profile.plist
(位于Contents/Resources
目录)文件,增加supportedArchs
属性,具体增加的内容如下:
注意事项:
- 建议先复制一份
profile.plist
文件到其他地方,修改完成后再替换原文件 - 如果遇到问题的iOS模拟器版本大等于iOS 14.0,那么应该不是同一个问题
- 实测Xcode 15 beta 5版本最低只支持iOS 13.7版本,而且可能因为配套使用的
Simulator.app
(Xcode内置)也还处于Beta版,运行调试会有点问题。 - 如果你还在用Xcode 14却遇到当前问题,建议按问题分析中的操作重装老版本的
CoreSimulator
框架
总的来说,如果Xcode 15正式版最低也只支持到iOS 13.7版本,那么后续想使用更低版本的iOS模拟器就只能通过Xcode 14。等正式版发布后,会重新测试并更新本篇文章。
以下是一些Xcode版本所支持的最低iOS模拟器版本:
最后更新日期:2023/08/10
Xcode version | CoreSimulator framework version | Minimum supported simulator version |
---|---|---|
14.0.1 | 857.7 | 12.0 |
14.2 | 857.14 | 12.0 |
14.3.1 | 885.2 | 12.0 |
15 beta 5 | 917 | 13.7 |
以上数据实测于M芯片的电脑,如果不是M芯片的电脑,可能会因为架构不一致有所差别。不过,更有可能是因为电脑上的Xcode版本和CoreSimulator
框架版本不一致导致的,当这两个版本不一致时以CoreSimulator
框架版本为主。
最后
如果这篇文章对你有所帮助,点赞👍加星🌟支持一下吧,谢谢~
本篇文章由@crasowas发布于CSDN。
相关文章:

iOS问题记录 - Xcode 15安装低版本iOS模拟器(持续更新)
文章目录 前言开发环境问题描述问题分析1. 定位问题2. 逆向分析2.1. IDA Free2.2. Hopper Disassembler Demo 3. 模拟器日志4. supportedArchs 解决方案最后 前言 最近新需求很多,项目改动很大,开发完成后想测一遍在低版本iOS系统上的兼容性,…...

高端百度地图开发2:自定义水滴头像(鼠标事件、API封装对接)
高端百度地图开发系列 高端百度地图开发1:自定义水滴头像(自定义标注覆盖物、Overlay覆盖类) 自定义水滴头像之鼠标事件、API封装对接 高端百度地图开发系列一、添加自定义覆盖物的方法二、对接API数据1.获取API数据(模拟)2.遍历数据3.添加自…...

R语言生存分析(机器学习)(2)——Enet(弹性网络)
弹性网络(Elastic Net):是一种用于回归分析的统计方法,它是岭回归(Ridge Regression)和lasso回归(Lasso Regression)的结合,旨在克服它们各自的一些限制。弹性网络能够同时考虑L1正则…...
【Docker】使用 Docker Registry 搭建自己的 Docker 镜像仓库
使用 Docker Registry 搭建自己的 Docker 镜像仓库 在使用 Docker 进行应用程序的开发和部署时,使用 Docker 镜像仓库是一个很好的实践。它允许集中存储和管理 Docker 镜像,方便团队协作和版本控制。在本文中,将介绍如何使用 Docker Registr…...
Spring 是什么框架?
Spring 是 Java EE 编程领域的一款轻量级的开源框架,由被称为“Spring 之父”的 Rod Johnson 于 2002 年提出并创立,它的目标就是要简化 Java 企业级应用程序的开发难度和周期。 Spring 自诞生以来备受青睐,一直被广大开发人员作为 Java 企业…...

Azure添加网络接口
添加网络接口的意义 在 Azure 上,为虚拟机添加网络接口的意义包括以下几个方面: 扩展网络带宽:通过添加多个网络接口,可以增加虚拟机的网络带宽,提高网络传输速度和数据吞吐量。实现网络隔离:每个网络接口…...

Linux 内核第一版 (v0.01) 开源代码解读
探索Linux v0.01的内部结构,Linux内核经常被认为是一个庞大的开源软件。在撰写本文时,最新版本是v6.5-rc5,包含36M行代码。不用说,Linux是几十年来许多贡献者辛勤工作的成果。 Linux 内核首个开源版本 (v0.01) 的体积非常小&…...
tp6 v3微信退款
/*** Notes:退款* param $out_trade_no 支付时候订单号(order表 original_bn)两个参数选一个这个要选对* param $out_refund_no 退款订单号* param $total 订单金额* param $refund 退款金额* Time: 2023-08-10*/public function refundMoney($out_trade…...

使用 AndroidX 增强 WebView 的能力
在App开发过程中,为了在多个平台上保持一致的用户体验和提高开发效率,许多应用程序选择使用 H5 技术。在 Android 平台上,通常使用 WebView 组件来承载 H5 内容以供展示。 一.WebView 存在的问题 自 Android Lollipop 起,WebVie…...

Maven基础之仓库、命令、插件机制
文章目录 Maven 仓库中央仓库和本地仓库中央仓库本地仓库 Maven 命令generate 命令compile 命令clean 命令test 命令package 命令install 命令 Maven 插件机制官方插件:Compile 插件Tomcat 7 插件 Maven 仓库 中央仓库和本地仓库 [✎] 简单一点说 中央仓库是一个网…...

【ArcGIS】经纬度数据转化成平面坐标数据
将点位置导入Gis中,如下(经纬度表征位置): 如何利用Gis将其转化为平面坐标呢? Step1 坐标变换 坐标变换,打开ArcToolbox,找到“数据管理工具”->“投影和变换”->“要素”->“投影”…...
使用自己的数据利用pytorch搭建全连接神经网络进行回归预测
使用自己的数据利用pytorch搭建全连接神经网络进行回归预测 1、导入库2、数据准备3、数据拆分4、数据标准化5、数据转换6、模型搭建7、模型训练8、模型预测9、完整代码 1、导入库 引入必要的库,包括PyTorch、Pandas等。 import numpy as np import pandas as pd f…...
103.216.154.X服务器出现漏洞了有什么办法?
服务器出现漏洞是一种严重的安全风险,需要及时采取措施来应对。以下是一些常见的应对措施: 及时更新补丁:确保服务器上的操作系统、应用程序和软件都是最新版本,并及时应用相关的安全补丁,以修复已知的漏洞。 强化访问…...

数据结构:堆的实现(C实现)
个人主页 : 个人主页 个人专栏 : 《数据结构》 《C语言》 文章目录 一、堆二、实现思路1. 结构的定义2. 堆的构建 (HeapInit)3. 堆的销毁 (HeapDestroy)4. 堆的插入 (HeapPush)5. 堆的删除 (HeapPop)6. 取堆顶的数据 (HeapTop)7. 堆的数据个数 (HeapSize…...

数据分析两件套ClickHouse+Metabase(一)
ClickHouse篇 安装ClickHouse ClickHouse有中文文档, 安装简单 -> 文档 官方提供了四种包的安装方式, deb/rpm/tgz/docker, 自行选择适合自己操作系统的安装方式 这里我们选deb的方式, 其他方式看文档 sudo apt-get install -y apt-transport-https ca-certificates dirm…...

urllib爬虫模块
urllib爬取数据 import urllib.request as request# 定义url url "https://www.baidu.com" #模拟浏览器发起请求获取响应对象 response request.urlopen(url)""" read方法返回的是字节形式的二进制数据 二进制--》字符串 解码 decode( 编码的格式…...

TCP消息传输可靠性保证
TCP链接与断开 -- 三次握手&四次挥手 三次握手 TCP 提供面向有连接的通信传输。面向有连接是指在数据通信开始之前先做好两端之间的准备工作。 所谓三次握手是指建立一个 TCP 连接时需要客户端和服务器端总共发送三个包以确认连接的建立。在socket编程中,这一…...
Visual Studio 与QT ui文件
对.ui文件鼠标右键,然后单击 Open with…在弹出的窗口中,选中左侧的 Qt Designer,然后单击右侧的 Add 按钮,随后会弹出一个窗口,在 Program: 输入框中输入 Qt Designer 的路径,最后单击 OK找到 Qt Designer…...

竞赛项目 深度学习验证码识别 - 机器视觉 python opencv
文章目录 0 前言1 项目简介2 验证码识别步骤2.1 灰度处理&二值化2.2 去除边框2.3 图像降噪2.4 字符切割2.5 识别 3 基于tensorflow的验证码识别3.1 数据集3.2 基于tf的神经网络训练代码 4 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 &#x…...

ORA-00845: MEMORY_TARGET not supported on this system
处理故障时,发现startup实例失败,报错ORA-00845: MEMORY_TARGET not supported on this system SYSorcl1> startup; ORA-00845: MEMORY_TARGET not supported on this system 查看alert日志,报错如下 Starting ORACLE instance (normal…...

MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...

逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...

高考志愿填报管理系统---开发介绍
高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发,采用现代化的Web技术,为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## 📋 系统概述 ### 🎯 系统定…...
Monorepo架构: Nx Cloud 扩展能力与缓存加速
借助 Nx Cloud 实现项目协同与加速构建 1 ) 缓存工作原理分析 在了解了本地缓存和远程缓存之后,我们来探究缓存是如何工作的。以计算文件的哈希串为例,若后续运行任务时文件哈希串未变,系统会直接使用对应的输出和制品文件。 2 …...