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

第3.4节 调用链路分析服务开发

3.4.1 什么是Code Call Graph(CCG)

Code Call Graph(CCG)即业务代码中的调用关系图,是通过静态分析手段分析并构建出的一种描述代码间关系的图。根据精度不同,一般分为类级别、方法级别、控制流级别,本文重点在方法级别上。
我们以一段代码进行举例:
class A {public void funA1() {funA2();C c = new C();c.funC1();}public void funA2() {B b = new B();b.funB1();}
}class B {public void funB1() {funB2();}public void funB2() {if (randN(10) < 5) {Logger.log("Hello B2");} else {funB2()}}
}class C {public void funC1() {B b = new B();b.funB2();}
}

如上代码所构建出的方法级别的CCG是这样的:

1,CCG的作用主要有两个

假设当我们出现一个需求改动到
1,funB1该方法时,我们可以从该图上进行逆向查找,找到所有直接调用或者间接调用该方法的所有方法A2,A1,这个代表对B2的改动,会影响到A2,A1,{B1, A2, A1}即方法B2的代码影响域。
2,在单元测试场景下,如果某个测试用例
testX是针对funC1的测试,那么我们可以从该方法上进行正向查找,找到所有它直接调用或者间接调用的方法B2,这个代表,我的测试用例testX的执行后可以测试到方法C1, B2,{B2, C1}即用例testX的关联代码。

2,CCG的应用场景

除了可以应用在精准测试场景下之外,还能在如下场景应用:
1,app启动或页面启动场景下的性能分析与性能优化:当我们要进行某个场景下的耗时优化时,我们可以从几个核心入口函数如android的下的application.onCreate(),application.onBaseContextAttached()的方法作为起点,查找后续调用方法,获知在整个启动流程里,哪些方法通过什么方式被执行了,帮助判断这种执行是否是启动场景下必须执行的任务。
2,组件化解耦:当我们需要判断两个组件间的耦合关系时,我们可以以其中一个组件中的方法作为起点,查找调用链上是否有另一个组件的方法,来寻找两个组件间的详细耦合关系,帮助后续进行解耦。相比传统静态分析方案,CCG可以更准确高效的查找出非直接依赖的隐性耦合。

3.4.2. CCG构建业界方案一览

目前业界有一部分相对完成度比较高的开源callgraph或者AST生成方案:

Android/Java

1,soot/wala等静态代码分析框架:GitHub - soot-oss/soot: Soot - A Java optimization framework,soot是比较完善的静态代码分析框架,从能力设计上都符合我们的需求,但是soot本身是一个通用性框架,没有专门为call graph场景去设计,比如匿名内部类,Runnable/Callable/Thread等线程类,lambda表达式,Stream调用,泛型处理等等,这些都需要我们去对soot做定制才能达到我们的需求。此外仅针对callgraph生成场景,soot设计是过复杂的,导致对于百万级方法节点的处理性能并不足够好。

2,java-all-call-graph: GitHub - Adrninistrator/java-all-call-graph: Generate all call graph for Java Code.,这个项目是一个比较简单的基于class字节码分析生成callgraph的方案,解决了soot的各种缺失能力,同时在处理性能上要优于soot。但是仍然存在一定缺陷,比如无法支持使用Redux框架进行开发的代码,反射,广播等场景。

iOS/Objc-c, swift

1,Drafter: GitHub - L-Zephyr/Drafter: 在iOS项目中自动生成类图和方法调用图 - Generate call graph in iOS project,Drafter是一个简单的语法+词法分析器,由于不带语义信息,只能支持单个类下的call graph生成,不符合我们的需求。
2,libTooling:官方工具,独立AST生成工具,libTooling可以生成一个完整的带语义分析的AST,我们可以基于该AST来生成所需的call graph,但是libTooling的性能非常差(需要为每个文件或者模块生成编译参数,并且无法应用各种编译优化),在全量情况下快手app的call graph生成耗时达到数小时,增量情况下一个500行文件的生成耗时达到几十秒,对于大型mr无法承受。
3,Clang Plugin:官方工具,集成进编译流程中的AST生成插件,clang plugin方案通过集成在编译流程里,目标产物为语义AST,由于可集成在编译流程中,我们可以复用包括gundum在内的各种编译优化手段,在增量情况下每个文件的生成耗时可以降到秒级,全量情况下为十几分钟。但是clang plugin只能支持oc代码,并且我们无法直接将打包集群的编译环境替换掉,因此我们需要在clang plugin基础上搞定swift/c++/c的支持,以及跨语言构建问题。同样的,我们还需要支持泛型、代理、redux、广播、KVO、oc runtime等特殊场景。

3.4.3 现在的CCG整体架构

CCG服务提供了Android,IOS调用钏的生成,序列化保存,查询等相关功能,以及对git diff获取diff函数的相关功能和接口。

3.4.4 . 流水线上CCG服务构建与更新流程

随着代码的改动,CCG需要同步更新,因此CCG服务需要与流水线深度关联。CCG服务主要分为3个阶段:

1,全量构建阶段

CCG全量构建基于定时触发,每隔固定时间(目前为24小时),CCG服务平台会触发一次双端全源码包构建请求,完成一次全量CCG构建,流程如下
如前文提到,CCG构建时需要使用特定jenkins脚本构建相关产物,获得产物后通过相关分析脚本得到完整版CCG:
生成出的完整版本CCG大概长上面这个样子,每个节点代表一个方法,我们需要存储该方法本身信息,其所属函数、参数列表,指向的前序与后序方法节点。对于一个超大型应用而言,我们可能有几百万个方法节点,这种存储方式最后得到的CCG产物十分庞大,内存占用达到几GB,显然这对内存、磁盘甚至CPU都是很大的负担(一个CCG服务器上需要同时维护多份CCG)。
因此我们在构建出全量CCG后,引入了CCG压缩流程,压缩后的CCG会被分成两部分:CCG-Node Map,CCG-Meta DB。压缩后的每个节点上只存储了该Node的hash值,并以此hash值作为key,构建meta DB,存储详细信息。在后续查询时,我们从Node Map中拿到对应的hash list后再从数据库中做一次sql查询,即可得到完整信息。这种方案也有利于获取扩展更多的节点信息,比如我们要增加线上用户热度图(见5.5)信息时,只需要在meta DB中插入即可。
全量构建完成的CCG我们称之为Base CCG,会以commitID作为版本号进行持久化。

2. 更新阶段

由于每个mr提交后都会改变局部CCG,因此我们需要引入实时CCG更新方案。我们选择引入git webhook监听所有mr merge操作,当一个mr合并入主分支后(dev分支),会触发CCG更新机制。整个更新机制分成两种平台,四种场景:
Android(复用产物分析)
场景1. 如果mr有新增/更新/删除单元测试case,一定会触发单元测试节点,此时我们根据mr diff与已经打好的单元测试包做一次增量分析,得到增量CCG
场景2. 如果mr没有相关单元测试case改动,我们根据mr diff与已经打好的编译检查包做一次增量分析,得到增量CCG
场景3. 如果因为各种原因没有匹配的编译检查包,我们需要触发一次jenkins debug包打包,再结合mr diff进行增量分析,得到增量CCG
iOS(无法使用产物结果,需要重新进行语义AST分析)
场景1. iOS场景下,在mr merge触发后,会直接触发jenkins打包服务,构建语义AST,与全量构建场景不同的是,这种场景下只会触发增量编译,因此语义AST构建只针对mr diff中的增量文件进行触发(目前主站增量编译是pod级缓存,AST构建也是pod级,当文件级缓存上线后,AST构建也将变成文件级)。
增量更新的CCG我们称之为Diff CCG,以mrId + 最新commitId作为索引值持久化,该CCG唯一绑定某个版本的Base CCG(取决于基于哪个base版本进行的diff),并存储指向对应版本的Base CCG的文件指针。
Diff CCG寻找绑定Base CCG的算法可以简化描述为:从提交mr对应的开发分支上向前寻找到最近的与dev分支的共同祖先节点,以这个节点commitId作为基准值,再向前寻找最邻近的关联有Base CCG的commitId,该Base CCG即目标CCG。
Question1. 为什么可以使用开发分支上的编译产物获取增量CCG并合入dev分支后的CCG?
事实上CCG的merge操作和git代码的merge操作是类似的,由于开发分支合并入dev分支时,代码层面一定不存在冲突,因此我们可以保证CCG merge时也不存在冲突。
另一方面对于代码层面的merge,最终可以归类为三种情况:add method,change method,delete method。这几种情况,反应到CCG上对应于添加一个方法节点,修改某个方法节点的出边,删除一个方法节点,可以实现一一对应。
因此我们在开发分支上获得增量CCG可以与当前mr的diff代码保证一一对应,merge进主干分支的CCG上时也等价于mr merge进主干分支。
Question2. 如果CCG更新太慢,后续mr所基于的dev分支代码已经领先于最新CCG会出现什么后果?
由于指向dev分支的merge操作是保证原子时序性的(不会出现两个merge操作并发执行),因此我们对于git merge的webhook也是时序性,在CCG更新操作上我们采用了同步非阻塞设计,即当出现一次merge操作后,我们触发更新操作,该更新操作会被push到执行队列中并立刻返回,执行队列是一个顺序的任务队列,保证前一个更新任务完全完成后,后一个才会执行。
当出现一个查询任务时,如果该查询任务所基于dev分支节点的CCG还未更新完成,为了避免阻塞等待,我们会使用最邻近CCG进行查询,这会带来一定程度的误差(事实上这种误差可以忽略,大多数情况下不会存在两个mr在很短的时间内去更新同一个功能模块)。

3,查询阶段

用户提交mr后,会通过流水线触发代码影响域查询服务,输入为mr diff文件,输出为受影响的方法list,以及相关权重信息。
  1. 查询可以分为两个阶段:
  2. mr diff分析找到所有改动方法
根据改动方法,在CCG上找到所有受影响的方法
MR Diff分析
MR分析阶段,我们会根据mr diff信息使用前置分析器找到变动方法,为了确保分析性能(MR分析阶段需要足够快,否则会影响整个流水线的执行速度),我们引入/自研了高性能的词法语法分析器作为我们的前置分析器,可以非常快的构建出一棵不带语义信息的AST。关于前置分析器的具体实现细节可见3.4、3.5节。
CCG查询阶段
拿到变动方法列表后,我们还无法直接进行查询,因为在CCG平台上存储的是一系列Base CCG和Diff CCG,我们需要找到并构建出我们的mr所匹配的CCG。
考虑如下的一个Git分支模型:
我们从Dev分支拉出Task分支后,当我们第一次提交mr到流水线上时(图中create MR),我们的CCG服务会基于该mr的最新commit(红色分支第二个节点)向前寻找最近一次checkout/merge/rebase Dev分支的节点(绿色第二个节点),找到该节点后,向CCG持久化服务中搜索对应的CCG图,此时我们找到了MR1-1 CCG,这是一个Diff CCG,该Diff CCG中存储了它依赖的Base CCG指针,然后对这两个CCG进行一次merge操作,即得到了我们想要的CCG(即CCG v1),在该图上即可进行后续的查询服务。当我们后续有新的commit提交到MR上时,重复上述操作即可获得新的CCG版本。
在具体查询上,我们根据变动类型将查询分为三类:
  1. 新增方法:新增方法不会影响其它方法,并且在没有匹配的新增case时,该新增方法也不会存在关联存量用例,而对于新增用例的场景,这些用例无论怎么样都会直接推荐,因此在CCG阶段直接忽略新增方法
  2. 删除方法:删除方法不会影响其它方法,也不会对测试产生影响,直接忽略
  3. 变更方法:变更方法是我们唯一需要进行查询的场景,我们以变更方法作为起始节点,向前追溯该方法的所有前序节点,即可获得对应变更方法的代码影响域,为了提供更多信息,我们会引入更多的权重信息来辅助后续的推荐策略,在第五章中会作详述。
至此整个CCG服务完成,作为一个单独的服务,为整个精准测试平台提供调用链路查询和分析相关功能。

相关文章:

第3.4节 调用链路分析服务开发

3.4.1 什么是Code Call Graph&#xff08;CCG&#xff09; Code Call Graph&#xff08;CCG&#xff09;即业务代码中的调用关系图&#xff0c;是通过静态分析手段分析并构建出的一种描述代码间关系的图。根据精度不同&#xff0c;一般分为类级别、方法级别、控制流级别&#x…...

超详细Docker教程

前言&#xff1a;大家在在Linux上部署mysql及其他软件时&#xff0c;大家想一想自己最大的感受是什么&#xff1f; 我相信&#xff0c;除了个别天赋异禀的人以外&#xff0c;大多数人都会有相同的感受&#xff0c;那就是麻烦。核心体现在三点&#xff1a; 命令太多了&#xff…...

探索AI新领域:生成式人工智能认证(GAI认证)助力职场发展

在数字化时代的大潮中&#xff0c;人工智能&#xff08;AI&#xff09;技术以其强大的影响力和广泛的应用前景&#xff0c;正逐步重塑我们的生活与工作方式。随着生成式AI技术的崛起&#xff0c;掌握这一前沿技能已成为职场竞争中的关键优势。那么&#xff0c;如何通过系统的学…...

sql sql复习

虽然之前学习过sql&#xff0c;但由于重在赶学习进度&#xff0c;没有学扎实&#xff0c;导致自己刷题的时候有的地方还是模模糊糊&#xff0c;现在主要是复习&#xff0c;补一补知识点。 今日靶场&#xff1a; NSSCTF 云曦历年考核题 在做题之前先回顾一下sql注入的原理&…...

初探 Skynet:轻量级分布式游戏服务器框架实战

在游戏服务器开发领域&#xff0c;高效、稳定且易于扩展的框架一直是开发者追求的目标。Skynet 作为一款轻量级、高性能的分布式游戏服务器框架&#xff0c;凭借其独特的设计理念和强大的功能&#xff0c;赢得了众多开发者的青睐 一.Skynet底层架构支持 1.Actor erlang 从语言…...

libarchive.so.19丢失

文章目录 绝对路径可以启动&#xff0c;相对路径不可以以绝对路径启动conda环境&#xff0c;运行python3.8(成功) 报错 Error while loading conda entry point: conda-libmamba-solver (libarchive.so.19: cannot open shared object file: No such file or directory) sudo a…...

vue-ganttastic甘特图label标签横向滚动固定方法

这个甘特图之前插件里&#xff0c;没有找到能固定label标签在屏幕上的办法&#xff0c;用css各种办法都没有实现&#xff0c;所以我我直接手写定位&#xff0c;用js监听滚动条滚动的距离&#xff0c;然后同步移动甘特图label标签&#xff0c;造成一种定位的错觉&#xff0c;以下…...

自动化 NuGet 包打包与上传:完整批处理脚本详解(含 SVN 支持)

在大型项目中&#xff0c;我们常常需要定期打包多个 .csproj 项目为 NuGet 包&#xff0c;并上传到私有 NuGet 服务。这篇文章分享一份实战脚本&#xff0c;支持以下自动化流程&#xff1a; 自动读取、更新 .csproj 文件中的 Version、PackageOutputPath 等节点&#xff1b; 自…...

Go语言空白导入的作用与用途

在 Go 语言中&#xff0c;导入包时前面加下划线 _ 是一种特殊的导入方式&#xff0c;称为 “空白导入” 或 “匿名导入”。 作用&#xff1a; 执行包的初始化&#xff08;init 函数&#xff09;但不直接使用包中的标识符 import _ "go.uber.org/automaxprocs" 表示你…...

实验六:按键模拟控制实现

FPGA序列检测器实验(远程实验系统) 文章目录 FPGA序列检测器实验(远程实验系统)一、数字电路基础知识1. 时钟与同步2. 按键消抖原理代码讲解:分频与消抖3. 有限状态机(FSM)设计代码讲解:状态机编码与转移4. 边沿检测与信号同步5. 模块化设计二、实验数字电路整体思想三…...

【愚公系列】《Manus极简入门》038-数字孪生设计师:“虚实映射师”

&#x1f31f;【技术大咖愚公搬代码&#xff1a;全栈专家的成长之路&#xff0c;你关注的宝藏博主在这里&#xff01;】&#x1f31f; &#x1f4e3;开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主&#xff01; &#x1f…...

Linux重定向与缓冲区

目录 文件描述符的分配规则 重定向 使用 dup2 系统调用 FILE 文件描述符的分配规则 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>int main() {int fd open("myfile", O_RDONLY);if(fd < 0){per…...

经典还原反应解析:Wolff-Kishner机制与黄鸣龙改进法

在有机化学发展史上记载的万余种经典反应中&#xff0c;当论及以科学家命名的标志性转化反应时&#xff0c;Wolff-Kishner-黄鸣龙还原反应必然占据重要地位。在大学《有机化学》课程中&#xff0c;学习还原反应时肯定会提到Wolff-Kishner-黄鸣龙还原反应&#xff0c;这是第一个…...

DataX从Mysql导数据到Hive分区表案例

0、下载DataX并解压到对应目录 DataX安装包&#xff0c;开箱即用&#xff0c;无需配置。 https://datax-opensource.oss-cn-hangzhou.aliyuncs.com/202308/datax.tar.gz 相关参考文档 https://github.com/alibaba/DataX/blob/master/hdfswriter/doc/hdfswriter.md 1、Hive分区…...

npm 报错 gyp verb `which` failed Error: not found: python2 解决方案

一、背景 npm 安装依赖报如下错&#xff1a; gyp verb check python checking for Python executable "python2" in the PATH gyp verb which failed Error: not found: python2 一眼看过去都觉得是Python环境问题&#xff0c;其实并不是你python环境问题&#xf…...

安装npm:npm未随Node.js一起安装

文章目录 上传至linux服务器/usr/local/目录下 如果npm没有随Node.js一起安装&#xff0c;你可以尝试单独下载并安装npm。但通常情况下&#xff0c;这是不必要的&#xff0c;因为npm是Node.js的一部分。如果确实需要单独安装npm&#xff0c;你可以参考npm的官方安装指南。 npm…...

C++23 ranges::to:范围转换函数 (P1206R7)

文章目录 引言C23 Ranges 概述ranges::to 的定义与功能定义功能 使用场景范围转换为容器简化字符串解析映射转换为向量 ranges::to 的优势代码简洁性提高开发效率与C23的stl容器的范围版本构造函数配合良好 模板参数约束的思考总结 引言 在C的发展历程中&#xff0c;每一个新版…...

openfeign 拦截器实现微服务上下文打通

目录 openfeign 拦截器实现微服务上下文打通需求分析&#xff1a;代码实现&#xff1a;subject 服务&#xff1a;controllerFeign 拦截器&#xff1a;将 Feign 拦截器注册为一个Bean&#xff1a; auth 鉴权服务&#xff1a;全局配置类&#xff1a;登录拦截器&#xff1a;上下文…...

【MySQL】变更缓冲区:作用、主要配置以及如何查看

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客仓库&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &…...

TCP/IP-——C++编程详解

1. TCP/IP 编程基本概念 TCP&#xff08;传输控制协议&#xff09;&#xff1a;面向连接、可靠的传输层协议&#xff0c;保证数据顺序和完整性。IP&#xff08;网际协议&#xff09;&#xff1a;负责将数据包路由到目标地址。Socket&#xff08;套接字&#xff09;&#xff1a…...

微服务如何实现服务的高可用

背景&#xff1a;微服务分层需要考虑高可用和高并发的问题 微服务如何实现服务的高可用 先说结论&#xff1a;微服务实现高可用主要通过集群冗余故障自动转移来实现的具体可以从底下几种方案来实现。 “端”到“反向代理”的高可用“反向代理”到“站点应用”的高可用“站点…...

微服务调试问题总结

本地环境调试。 启动本地微服务&#xff0c;使用公共nacos配置。利用如apifox进行本地代码调试解决调试问题。除必要的业务微服务依赖包需要下载到本地。使用mvn clean install -DskipTests进行安装启动前选择好profile环境进行启动&#xff0c;启动前记得mvn clean清理项目。…...

egpo进行train_egpo训练时,keyvalueError:“replay_sequence_length“

def execution_plan(workers: WorkerSet, config: TrainerConfigDict) -> LocalIterator[dict]: if config.get(“prioritized_replay”): prio_args { “prioritized_replay_alpha”: config[“prioritized_replay_alpha”], “prioritized_replay_beta”: config[“prior…...

Hadoop的组成

&#xff08;一&#xff09;Hadoop的组成 对普通用户来说&#xff0c; Hadoop就是一个东西&#xff0c;一个整体&#xff0c;它能给我们提供无限的磁盘用来保存文件&#xff0c;可以使用提供强大的计算能力。 在Hadoop3.X中&#xff0c;hadoop一共有三个组成部分&#…...

Android锁

引言 &#x1f512; 在 Android 应用的开发过程中&#xff0c;随着业务需求的复杂度不断提升&#xff0c;多线程并发场景层出不穷。为了保证数据一致性与线程安全&#xff0c;锁&#xff08;Lock&#xff09;成为了不可或缺的工具。本篇博客将深入剖析 Android 中常用的锁机制…...

XD08M3232接近感应单片机的接近感应模块的工作原理

XD08M3232接近感应单片机的接近感应模块基于电容式感应原理&#xff0c;通过硬件电路与软件配置实现对物体接近的检测。以下是其工作原理的详细解析&#xff1a; 一、硬件架构与核心组件 1. 核心电路组成 接近感应模块由三大关键部分构成&#xff1a; 两个轨到轨运算放大器&…...

编程日志5.6

串的习题 1.2236. 判断根结点是否等于子结点之和 - 力扣(LeetCode) /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * Tr…...

量子计算实用化突破:从云端平台到国际竞合,开启算力革命新纪元

在硅谷某生物医药实验室&#xff0c;研究员艾米丽正盯着量子计算模拟界面露出微笑 —— 搭载中电信 "天衍" 量子计算云平台的 880 比特超导量子处理器&#xff0c;用 17 分钟完成了传统超算需 3 个月才能跑完的新型抗生素分子键合模拟。这个场景标志着量子计算正从 &…...

Made with Unity | 拓展“双点”宇宙版图

双点工作室&#xff08;Two Point Studios&#xff09;团队成立于2016年&#xff0c;其创立初衷是打造一个完美的游戏IP&#xff1a;构建一个既能持续吸引玩家&#xff0c;又具备足够扩展空间&#xff0c;同时经得起时间考验的虚拟世界。2018年&#xff0c;团队以《双点医院&am…...

3D 数据可视化系统是什么?具体应用在哪方面?

目录 一、3D 数据可视化系统的定义与内涵 &#xff08;一&#xff09;基本概念 &#xff08;二&#xff09;核心要素 二、3D 数据可视化系统的优势 三、3D 数据可视化系统的应用领域 &#xff08;一&#xff09;城市规划与管理 &#xff08;二&#xff09;工业制造 &am…...

2025-5-14渗透测试:利用Printer Bug ,NTLMv2 Hash Relay(中继攻击),CVE-2019-1040漏洞复现

python3 printerbug.py test.com/test192.168.186.131 192.168.186.134 sudo python2 MultiRelay.py -t 192.168.186.132 -u ALLPrinter Bug 原理 PrinterBug&#xff08;CVE-2018-0886&#xff09;是Windows打印系统服务&#xff08;Spooler&#xff09;的一个设计缺陷&…...

OracleLinux7.9-ssh问题

有套rac环境&#xff0c;db1主机无法ssh db1和db1-priv&#xff0c;可以ssh登录 db2和db2-priv [rootdb1 ~]# ssh db1 ^C [rootdb1 ~]# ssh db2 Last login: Wed May 14 18:25:19 2025 from db2 [rootdb2 ~]# ssh db2 Last login: Wed May 14 18:25:35 2025 from db1 [rootdb2…...

《AI大模型应知应会100篇》第64篇:构建你的第一个大模型 Chatbot

第64篇&#xff1a;构建你的第一个大模型 Chatbot 手把手教你从零开始搭建一个基于大模型的聊天机器人 摘要 你是否想过&#xff0c;自己也能构建一个像 ChatGPT 一样能对话、能思考的聊天机器人&#xff08;Chatbot&#xff09;&#xff1f;别担心&#xff0c;这并不需要你是…...

鸿蒙OSUniApp 实现精美的用户登录和注册页面#三方框架 #Uniapp

UniApp 实现精美的用户登录和注册页面 前言 在开发鸿蒙APP时&#xff0c;登录注册页面作为用户与应用交互的第一道门槛&#xff0c;其体验与质量往往决定了用户的第一印象。去年我接手了一个电商小程序项目&#xff0c;产品经理特别强调要做一个既美观又实用的登录注册页面。…...

c#中equal方法与gethashcode方法之间有何关联?

文章目录 前言一、对hash运算的深入思考二、equal与gethashcode的关联三、 equal与gethashcode不同步的后果四、 规范的重写gethashcode 前言 大家有没有遇到过&#xff0c;当你重写了c#对象的equal方法之后&#xff0c;编译器会提示你对相应的gethashcode进行重写&#xff0c…...

查询公网IP地址的方法:查看自己是不是公网ip,附内网穿透外网域名访问方案

本地搭建服务并提供互联网连接时&#xff0c;较为传统的方法是使用公网IP地址。因此&#xff0c;如何查询本地自己是不是公网IP&#xff0c;是必须要掌握的一种技巧。当面对确实无公网IP时&#xff0c;则可以通过内网穿透方案&#xff0c;如nat123网络映射工具&#xff0c;将本…...

【轻松学 C:编程小白的大冒险】— 16 函数的定义与调用

在编程的艺术世界里&#xff0c;代码和灵感需要寻找到最佳的交融点&#xff0c;才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里&#xff0c;我们将共同追寻这种完美结合&#xff0c;为未来的世界留下属于我们的独特印记。 【轻松学 C&#xff1a;编程小白的大冒险…...

【Tools】CPU 分析

CPU 分析 Windows SDK 本指南提供了可用于调查影响评估指标的中央处理单元 (CPU) 相关问题的详细技术。 特定于评估的分析指南中的各个指标或问题部分确定了需要调查的常见问题。 本指南提供了可用于调查这些问题的技术和工具。 本指南中的技术使用 Windows Performance Too…...

进阶2_1:QT5多线程与定时器共生死

1、在widget.ui中使用 LCD Number控件 注意&#xff1a;若 LCD 控件不是多线程&#xff0c;LCD控件则会瞬间自增到最大的数值&#xff0c;如上图&#xff0c;说明两者都是多线程处理 2、实现方式 1、创建 LCD 控件并修改为 LCD1 2、创建任务类 mytask. h&#xff0c;对任务类…...

ECharts:数据可视化的强大引擎

在当今这个信息爆炸的时代&#xff0c;如何有效地展示和理解复杂的数据成为了每一个开发者和技术爱好者面临的挑战。Apache ECharts 作为一款基于 JavaScript 的开源可视化库&#xff0c;以其强大的功能、丰富的图表类型以及高度的可定制性&#xff0c;迅速成为了数据可视化领域…...

记录 QT 在liunx 下 QFileDialog 类调用问题 ()Linux下QFileDialog没反应)

1. 2025.05.14 踩坑记录 因为QT 在 liunx 文件系统不同导致的 Windows &#xff1a; QString filePath QFileDialog::getOpenFileName(nullptr, "选择文件", ".", "文本文件 (*.txt);所有文件 (*.*)"); 没问题 liunx 下 打不开&#xff…...

通用软件项目技术报告 - 导读III

现在,我们正式进入报告的第六个主要领域:6. 领域六:与第三方服务/API 集成 (含 LLM API)。 连接: 在现代软件开发中,很少有应用程序是完全孤立的。我们经常需要与各种外部的第三方服务或 API 进行集成,以利用它们提供的特定功能(如支付处理、地图服务、社交媒体登录、云…...

Kali Linux 桌面环境安装与配置指南

一、为什么选择 Kali Linux&#xff1f; Kali Linux 由 Offensive Security 维护&#xff0c;集成了数百种安全测试工具&#xff08;如 Metasploit、Nmap 和 Burp Suite&#xff09;&#xff0c;非常适合安全研究。但需要注意的是&#xff0c;Kali 默认以 root 用户运行&#…...

FFmpeg视频编码的完整操作指南

步骤如下&#xff1a; 安装和准备FFmpeg&#xff1a;确保包含所需编码器&#xff08;如libx264&#xff09;。基本命令行编码&#xff1a;使用ffmpeg命令进行转码&#xff0c;设置视频编码器、CRF、预设等。API编码流程&#xff08;针对开发者&#xff09;&#xff1a; a. 注册…...

【网络协议】TCP、HTTP、MQTT 和 WebSocket 对比

从协议本质、工作原理、特点、应用场景等方面详细对比 TCP、HTTP、MQTT 和 WebSocket。 1. TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09; 本质 协议类型&#xff1a;传输层协议&#xff08;OSI模型第4层&#xff09;。核心功能&#x…...

Leetcode数组day1

704 二分查找 注意点&#xff0c;左闭右闭 class Solution { public:int search(vector<int>& nums, int target) {//整数类型的动态数组的引用。int left0;int right nums.size()-1;while (left < right){int middle (rightleft)/2;if (nums[middle]>targ…...

leetcode2934. 最大化数组末位元素的最少操作次数-medium

1 题目&#xff1a;最大化数组末位元素的最少操作次数 官方标定难度&#xff1a;中 给你两个下标从 0 开始的整数数组 nums1 和 nums2 &#xff0c;这两个数组的长度都是 n 。 你可以执行一系列 操作&#xff08;可能不执行&#xff09;。 在每次操作中&#xff0c;你可以选…...

常见相机焦段的分类及其应用

相机焦段是指镜头的焦距范围&#xff0c;决定了拍摄时的视角、画面范围和透视效果。不同焦段适合不同的拍摄场景和主题&#xff0c;以下是常见焦段的分类及其应用&#xff1a; 一、焦段的核心概念 焦距&#xff1a;镜头光学中心到成像传感器的距离&#xff08;单位&#xff1a…...

FPGA在光谱相机中的核心作用

FPGA&#xff08;现场可编程门阵列&#xff09;作为光谱相机的核心控制与加速单元&#xff0c;通过硬件级并行处理能力和动态可编程特性&#xff0c;实现高速、高精度的光谱数据采集与处理。以下是其具体作用分类&#xff1a; 一、高速光电信号处理 ‌实时光谱复原‌ 通过硬…...

【证书与信任机制​】证书透明度(Certificate Transparency):如何防止恶意证书颁发?​​

证书透明度&#xff08;Certificate Transparency, CT&#xff09;的核心原理 证书透明度&#xff08;CT&#xff09;是一项由Google主导的开放标准&#xff0c;旨在通过公开记录所有SSL/TLS证书的颁发行为&#xff0c;防止恶意CA错误或故意颁发虚假证书。其核心机制如下&#…...