【区块链安全 | 第三十七篇】合约审计之获取私有数据(一)
文章目录
- 私有数据
- 访问私有数据实例
- 存储槽
- Solidity 中的数据存储方式
- 1. storage(持久化存储)
- 定长数组
- 变长数组
- 2. memory(临时内存)
- 3. calldata
- 可见性关键字
- 私有数据存储风险
- 安全措施
私有数据
私有数据(Private Data)通常指的是只对特定主体可见或可访问的数据,在区块链环境中,它通常与隐私保护和访问控制相关。
在智能合约中,标记为 private 的变量或函数,仅在当前合约内部可访问,外部合约无法直接访问它们。
举个例子,对于该合约:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract Vault {// password 是一个 private 字段,只能在当前合约中使用string private password = "super_secret_password";address public owner;constructor() {owner = msg.sender;}function unlock(string memory _password) public view returns (bool) {// 函数 unlock 接受一个字符串,调用时会判断输入的密码是否等于合约内的 passwordreturn keccak256(abi.encodePacked(_password)) == keccak256(abi.encodePacked(password));}
}
外部合约不能直接访问 password,如果你写一个别的合约来调用 Vault.password(),会直接报错:变量是 private。
但 Solidity 中的 private 并不意味着区块链层面上的真正“不可见”,因为所有链上数据都是公开透明的,可以通过区块链浏览器或节点还原查看。
我们可以使用 Etherscan 的“Read Contract → storage”工具,或者自己写脚本来读取私有数据。
然后调用 unlock(password),轻松通过验证,进而调用 Vault 合约的其他功能。
访问私有数据实例
1.打开 Remix IDE。
2.在左侧的 File Explorer 中创建一个新文件,命名为 vault.sol。
3.将上文所述的合约代码粘贴到文件中:
4.在 Remix 中,切换到 Solidity Compiler(左侧面板的第二个选项)。
5.确保编译器版本选择的是 0.8.0 或更高版本。
6.点击“Compile vault.sol”按钮来编译合约。
7.切换到 Deploy & Run Transactions 面板(左侧的第三个选项)。
8.环境需要选择线上环境,这里我们选择本地环境,点击“Deploy”按钮部署合约。
9.通过上图的控制台输出可以看到,我们部署的合约地址为:
0x358AA13c52544ECCEF6B0ADD0f801012ADAD5eE3
10.新建 JS 文件,添加以下代码:
(async () => {const addr = "0x358AA13c52544ECCEF6B0ADD0f801012ADAD5eE3"; // 合约地址const raw = await web3.eth.getStorageAt(addr, 0);// 输出存储槽内容(原始十六进制数据)console.log("Raw hex:", raw);// 如果存储槽数据是字符串,解码console.log("Decoded password:", web3.utils.hexToUtf8(raw));
})();
11.鼠标右键JS文件并运行:
12.输出如下:
running 1.js ...
Raw hex:
0x0
Decoded password:
为何返回的是 0x0 呢?
这是因为我们是在 Remix 的本地虚拟机(Remix VM)环境中部署的合约,而脚本访问的是主网上的同一个合约地址。尽管地址看起来相同,但由于本地环境与主网并不共享状态,脚本实际读取的是主网上该地址的存储数据,而不是我们本地部署的合约数据。因此返回的是 0x0,而不是我们在本地设置的值。
我们可以查询部署在以太坊主网的真实合约地址:
https://etherscan.io/address/0x358AA13c52544ECCEF6B0ADD0f801012ADAD5eE3
如果你想将合约部署到真实区块链上,可以在 Remix 中选择 WalletConnect 或 Injected Provider - MetaMask 环境,并连接你的 MetaMask 钱包。不过要注意,部署到链上会消耗实际的 Gas 费用:
最终,我们获取到 password,就可以使用 unlock 函数来验证密码。
示例 JS 代码如下:
const vaultInstance = new web3.eth.Contract(abi, vaultAddress);
const isUnlocked = await vaultInstance.methods.unlock("super_secret_password").call();console.log(isUnlocked); // 输出 true
存储槽
从上文访问私有数据的 JavaScript 代码中你可以看到,我们通过如下语句读取合约中的存储数据:
const raw = await web3.eth.getStorageAt(addr, 0);
实际上获取的是合约地址 addr 下 slot 0 的数据。
那么,什么是 slot 0 呢?slot 称为存储槽,在 Solidity 中,所有的状态变量都会被存储在一个叫做 “存储槽(storage slot)” 的位置中。每个槽的大小为 32 字节(256 位),以太坊使用这些槽来组织和存储合约的数据。编译器会根据变量的声明顺序和类型,自动为它们分配对应的 slot 编号。
由于我们在合约中只定义了一个私有数据,因此其 slot 编号为 0(从 0 开始)。
接下来,我们顺带复习下 Solidity 中的数据存储方式。
Solidity 中的数据存储方式
Solidity 中的数据主要存储在三种位置:storage、memory 和 calldata。这三者在生命周期、读写成本、用途上都有明显区别。
1. storage(持久化存储)
在 Solidity 中,合约里的状态变量(包括 private、public 等)默认都存储在 storage 中。storage 是以太坊上的永久存储区域,写入的数据会记录在区块链上,因此读写成本较高。
底层上,Solidity 使用插槽(slot)来组织这些数据,每个 slot 固定为 32 字节(256 位)。编译器会根据变量在代码中声明的顺序为它们依次分配 slot。小于 32 字节的变量可能会被打包进同一个 slot(从右向左排列),而大于等于 32 字节的变量就会独占一个或多个新的 slot 来存储。
举个例子,假设我们有变量 varA(15 字节)、varB(10 字节)、bigVar2(35 字节),那么存储情况如下:
slot1: [ 剩余7字节,不满足vigVar2 | varA(15 字节) | varB(10 字节) ]<---------------- 从右向左存储 --------------->slot2: [ bigVar2(35 字节) ]
storage 中还有定长数组和变长数组的概念。
定长数组
定长数组的每个元素不管大小,都直接占用一个完整的插槽,连续存放在声明位置后面。
示例如下:
// 声明一个 uint16 类型的定长数组arr3,长度为 8,假设该数组分配在 slot 10 开始
uint16[8] arr3; 则:
slot 10: [ arr3[0](占用一个完整的 slot,虽然 uint16 是 2 字节,但仍占一个 32 字节的 slot) ]
slot 11: [ arr3[1](占用一个完整的 slot,虽然 uint16 是 2 字节,但仍占一个 32 字节的 slot) ]
slot 12: [ arr3[2](占用一个完整的 slot,虽然 uint16 是 2 字节,但仍占一个 32 字节的 slot) ]
slot 13: [ arr3[3](占用一个完整的 slot,虽然 uint16 是 2 字节,但仍占一个 32 字节的 slot) ]
变长数组
在处理变长数组时,Solidity 会采用特定的存储策略来应对其长度在编译期无法确定的问题。
当声明一个变长数组时,Solidity 会使用一个新的存储槽 slotA 来存储该数组的长度。数组的实际数据则不会紧接着存储在 slotA 后面,而是通过一个哈希运算确定其起始存储位置 slotV。
- slotA 表示变长数组在存储中的声明位置;
- length = sload(slotA):表示从 slotA 读取数组的长度;
- slotV = keccak256(slotA):通过 keccak256(slotA) 计算出数据部分的起始插槽;
- value = sload(slotV + index):第 index 个元素存储在 slotV + index 的位置,读取方式为 sload(slotV + index)。
由于变长数组在编译期无法确定其长度,因此无法预留连续的存储空间。为了解决这一问题,Solidity 选择将长度单独存储在 slotA,而将实际的数据映射到从 keccak256(slotA) 开始的一段存储空间中,以避免与其他变量产生冲突,并实现灵活的数据扩展。
2. memory(临时内存)
在 Solidity 中,memory 是一种临时的数据存储位置,数据仅在函数执行期间存在,函数调用结束后会被自动释放。它主要用于函数中临时变量的处理,比如函数参数、局部数组或结构体等。与永久存储的 storage 相比,memory 的读写成本更低一些,因此在处理临时数据时更加高效。不过,相较于 calldata,它的成本稍高一些。
需要注意的是,memory 中的数据不会被写入区块链,修改它也不会影响链上的状态,因此它适合用于函数内部的逻辑处理而非持久化存储。
3. calldata
在 Solidity 中,calldata 是一种只读的临时数据存储位置,专门用于存放函数的外部调用参数。它的数据存储在 EVM 的调用数据区,不会被写入链上,且在整个函数执行期间保持不变。
由于 calldata 是不可修改的,相比 memory 来说更省 gas,尤其是在处理大批量的外部输入数据时非常高效。因此,在 external 函数中,推荐将参数声明为 calldata,尤其是数组或结构体类型,以提升执行效率和节省成本。
可见性关键字
在了解 Solidity 中的三种存储方式后,我们再来看合约中的四种可见性关键字。Solidity 提供了四种可见性关键字:external、public、internal 和 private。默认情况下,函数的可见性为 public,而对于状态变量,除了不能使用 external 来定义,其他三个关键字都可以使用。状态变量的默认可见性为 internal。
external 关键字
使用 external 修饰的函数可以被外部合约调用。值得注意的是,external 函数不能在合约内部直接调用,必须使用 this.function() 的方式进行调用。
public 关键字
使用 public 修饰的函数不仅可以被外部调用,也可以在合约内部调用。对于使用 public 修饰的状态变量,Solidity 会自动生成一个 getter 函数,使得外部能够访问该变量。
internal 关键字
使用 internal 修饰的函数和状态变量只能在当前合约或其派生合约中访问。也就是说,internal 修饰的元素不能被外部合约直接访问。
private 关键字
使用 private 修饰的函数和状态变量仅对定义它的合约可见,派生合约无法访问或调用这些函数和状态变量。
综上所述,合约中使用可见性关键字修饰的变量和函数,主要限制了其调用范围,但并不限制其是否可读。因此,即使是 private 或 internal 的状态变量,只要能够通过特定方法访问,仍然是可以读取的。接下来,我们将深入探讨如何读取合约中的所有数据。
私有数据存储风险
所有状态变量都会被写入区块链的存储(storage)中,对所有链上用户公开可见。
从上述示例中我们也可以看出,任何人都可以访问链上任意合约的私有数据。因此,Solidity 中的 private
修饰符并不真正提供数据隐私,它仅在合约内部限制访问权限,对链外用户并无保护作用。
安全措施
1.敏感数据(如密码)不应以明文形式存储在链上;
2.在上链前对数据进行哈希处理(例如,仅存储 keccak256(password) 的结果);
3.避免在合约中保存明文密码,即使使用 private 也无法阻止链上其他人读取。
在下篇文章中,将通过具体合约代码进行案例分析。
相关文章:
【区块链安全 | 第三十七篇】合约审计之获取私有数据(一)
文章目录 私有数据访问私有数据实例存储槽Solidity 中的数据存储方式1. storage(持久化存储)定长数组变长数组 2. memory(临时内存)3. calldata 可见性关键字私有数据存储风险安全措施 私有数据 私有数据(Private Dat…...
20250408在荣品的PRO-RK3566开发板使用Rockchip原厂的buildroot系统时拿掉经常出现的list-iodomain.sh警告信息
rootrk3566-buildroot:/usr/bin# vi list-iodomain.sh rootrk3566-buildroot:/usr/bin# sync 【最后】 #chk_env #get_chip_id $1 #echo_msg "Get CHIP ID: $CHIP_ID" #get_iodomain_val 20250408在荣品的PRO-RK3566开发板使用Rockchip原厂的buildroot系统时拿掉经常…...
上下拉电阻详解
一、基本定义 上拉电阻:连接信号线与电源(VCC),确保信号在无驱动时保持高电平。 下拉电阻:连接信号线与地(GND),确保信号在无驱动时保持低电平。 二、核心作用 电平稳定 防止悬空引…...
特权FPGA之数码管
case语句的用法: 计数器不断的计数,每一个num对应数码管一种数据的输出。实例通俗易懂,一目了然。 timescale 1ns / 1ps// Company: // Engineer: // // Create Date: // Design Name: // Module Name: // Project Name: //…...
PyTorch 学习笔记
环境:python3.8 PyTorch2.4.1cpu PyCharm 参考链接: 快速入门 — PyTorch 教程 2.6.0cu124 文档 PyTorch 文档 — PyTorch 2.4 文档 快速入门 导入库 import torch from torch import nn from torch.utils.data import DataLoader from torchvision …...
MCP基础学习计划:从MCP入门到项目构建的全面指南
文章简介 ai生成的学计划有的连接是无效的,想着边学习边找输出文章,后续会继续链接更新 在人工智能和大语言模型(LLM)的快速发展下,掌握Model Context Protocol(MCP)成为提升AI应用能力的关键。…...
NO.77十六届蓝桥杯备战|数据结构-单调队列|质量检测(C++)
什么是单调队列? 单调队列,顾名思义,就是存储的元素要么单调递增要么单调递减的队列。注意,这⾥的队列和普通的队列不⼀样,是⼀个双端队列。单调队列解决的问题 ⼀般⽤于解决滑动窗⼝内最⼤值最⼩值问题,以…...
【有啥问啥】深入浅出讲解 Teacher Forcing 技术
深入浅出讲解 Teacher Forcing 技术 在序列生成任务(例如机器翻译、文本摘要、图像字幕生成等)中,循环神经网络(RNN)以及基于 Transformer 的模型通常采用自回归(autoregressive)的方式生成输出…...
redis数据迁移之通过redis-dump镜像
这里写目录标题 一、redis-dump 镜像打包1.1 安装windows docker1.2 idea项目创建1.3 idea镜像打包 二、redis数据迁移2.1 数据导出2.2 数据导入 一、redis-dump 镜像打包 没有找到可用的redis-dump镜像,需要自己打包一下,这里我是在idea直接打包的 1.…...
Redis哨兵模式下执行sentinel failover mymaster命令可能导致什么风险,如何避免
在 Redis 哨兵模式下执行 SENTINEL FAILOVER mymaster 命令会强制触发主节点切换(手动故障转移),虽然这是合法的管理操作,但可能带来以下风险及规避方法: 一、潜在风险 数据丢失风险 原因:主节点可能在故障…...
软考案例分析实例答题模板
案例分析(全部为主观问答题, 总 5 大题, 第一题必选, 剩下 4 选 2, 每题 25 分, 共75分) 第一题: 案例分析——某企业信息架构优化项目 案例材料: 某企业是一家从事电子商务的大型企业, 随着业务规模的不断扩大, 现有的信息架 构已无法满足企业快速发展的需求。 企业…...
Docker+Jenkins+Gitee自动化项目部署
前置条件 docker安装成功 按照下面配置加速 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-EOF {"registry-mirrors": ["https://register.librax.org"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker一、…...
olib开源图书
8.olib开源图书 该软件作者已开源,开源地址:开源地址:https://github.com/shiyi-0x7f/o-lib 点击该软件,使用管理员权限打开,进入界面可以搜索图书并下载pdf文件。 蓝奏云下载:https://wwph.lanzout.com/…...
react: styled-components实现原理 标签模版
styled-components是针对react中一个前端广泛使用的css-in-js样式库B站 利用标签模版 利用ES6中的 标签模版文档标签模板其实不是模板,而是函数调用的一种特殊形式。“标签”指的就是函数,紧跟在后面的模板字符串就是它的参数。 let a 5; let b 10;…...
AI大模型从0到1记录学习 day15
14.3.5 互斥锁 1)线程安全问题 线程之间共享数据会存在线程安全的问题。 比如下面这段代码,3个线程,每个线程都将g_num 1 十次: import time import threading def func(): global g_num for _ in range(10): tmp g_num 1 # ti…...
macbook pro查询并修改命令提示符的格式
环境 MacBook Pro 描述 我的命令提示符总是: # 前面总是多了(base) (base) yutaoyutaodeMacBook-Pro ~ % vim .zshrc (base) yutaoyutaodeMacBook-Pro ~ % source .zshrc # 期望改成下面这样: yutaoyutaodeMacBook-Pro ~ % 找…...
Baumer工业相机堡盟工业相机如何处理偶发十万分之一或百万分之一几率出现的黑图现象(C#)
Baumer工业相机堡盟工业相机如何处理偶发十万分之一或百万分之一几率出现的黑图现象(C#) Baumer工业相机Baumer工业相机出现黑图的技术背景硬件层面软件层面环境因素 实际案例演示:BaumerVCXG-53M.I.XT 防护相机项目使用环境项目反馈问题项目…...
基于Resemblyzer 声纹识别门禁系统设计
一、整体结构与思路 这份程序的核心目的是: 用麦克风录音 ➜ 识别说话人是谁 ➜ 图形化展示 ➜ 语音播报反馈 它主要由 4 个部分组成: 全局配置和依赖加载 语音采集和声纹提取逻辑 图形界面与交互(PyQt5) 语音播报反馈系统 …...
分布式数据库LSM树
LSM树的核心结构与操作流程 Log-Structured Merge Tree,日志 结构化 合并 树。 追加写:永远不改,就算是update操作,也是追加写,一直新生成文件。 刷盘触发:追加到一定程序,比如到了几M…...
2143 最少刷题数
2143 最少刷题数 ⭐️难度:中等 🌟考点:2022、前缀和、省赛、二分 📖 📚 import java.util.Scanner; import java.util.Arrays;public class Main2 {public static void main(String[] args) {Scanner sc new Sca…...
Ansible:playbook 使用when和ith_items
文章目录 playbook使用 whenplaybook 使用迭代 with_items迭代嵌套子变量 if 和 for在template中使用了,在playbook中加以区分,因此使用when进行条件判断,with_items进行循环迭代 playbook使用 when when语句,可以实现条件测试。…...
python爬取1688.item_search_best-查询榜单列表返回数据说明
在当今数字化时代,电商平台的数据蕴含着巨大的商业价值。1688作为国内领先的B2B电商平台,其商品搜索榜单数据能够为供应商、采购商以及市场研究人员提供诸多洞察。本文将详细介绍如何使用Python爬取1688的商品搜索榜单数据,并对返回数据进行说…...
数据结构(一)KMP+滑动窗口+链表+栈+队列
数据结构-链表 单链表 #include<iostream> using namespace std; const int N 100010; int head,e[N],ne[N],idx; void init() {head -1;idx 0; } void add_to_head(int x) {e[idx] x;ne[idx] head;head idx;idx; } void add(int k,int x) {e[idx] x;ne[id…...
C语言 数据结构 【队列】动态模拟实现
引言 用动态方式模拟实现队列的各个接口 一、队列的结构与概念 概念:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列…...
Python | 第十三章 | 多态 | 魔术方法 | 静态方法 | 抽象类
P130 多态练习题(1)2025/2/21 一、isinstance函数 基本说明: isinstance()用于判断对象是否为某个类或其子类的对象基本语法:isinstance(object,classinfo)解读形参: object:对象 classinfo:可以是类名、基本类型或者由它们组成…...
线程安全问题的原因与解决方案总结
目录 一 什么是线程安全? 二 线程安全问题的实例 三 线程安全问题的原因 1.多个线程修改共享数据 2.抢占式执行 3.修改操作不是原子的 4.内存可见性问题 5.指令重排序 四 解决方案 1.同步代码块 2.同步方法 3.加锁lock解决问题 一 什么是线程安全&…...
设计模式-模版方法
目录 什么是模版方法? 怎么理解抽象类的算法骨架? Burn功能骨架 战士类 法师类 什么是模版方法? 借助抽象类定义算法的骨架,再由具体子类实现算法的特定步骤。这种设计模式让算法的整体结构得以固定,同时又能让不…...
c# 运用策略模式与模板方法模式实例
策略模式 策略模式的核心在于定义一系列算法,把它们封装起来,并且让它们能够相互替换。策略模式让算法的变化独立于使用算法的客户端。在这个方法里,策略模式的体现如下: convertFunc 参数:这是一个委托类型的参数&a…...
基于51单片机的3路温度报警器proteus仿真
地址: https://pan.baidu.com/s/1qrCpGuzZRbeFVVjaGMffQA 提取码:1234 仿真图: 芯片/模块的特点: AT89C52/AT89C51简介: AT89C51 是一款常用的 8 位单片机,由 Atmel 公司(现已被 Microchip 收…...
llama-factory微调qwen2.5-vl
本文不生产技术,只做技术的搬运工!!! 前言 目前大模型百花齐放,微调方法复杂多样,且教程复杂,工程端想要进行垂域模型适配困难重重,本篇博客详细介绍了qwen2.5-vl的全流程微调过程,包括环境配置、数据集制作、模型训练、模型导出、模型部署、模型推理等过程,希望对工…...
淘宝历史价格采集合规指南:官方 API + 轻量爬虫混合方案
在电商数据分析领域,获取淘宝商品的历史价格数据对于企业制定价格策略、进行竞品分析以及消费者洞察市场价格波动趋势都具有重要意义。然而,由于淘宝平台对数据安全和合规性的严格要求,历史价格采集工作需要在合法合规的框架内进行。本文将详…...
文档控件DevExpress Office File API v24.2亮点:不再支持非Windows系统
DevExpress Office File API是一个专为C#, VB.NET 和 ASP.NET等开发人员提供的非可视化.NET库。有了这个库,不用安装Microsoft Office,就可以完全自动处理Excel、Word等文档。开发人员使用一个非常易于操作的API就可以生成XLS, XLSx, DOC, DOCx, RTF, CS…...
TDengine.C/C++ 连接器
简介 C/C 开发人员可以使用 TDengine 的客户端驱动,即 C/C 连接器(以下都用 TDengine 客户端驱动表示),开发自己的应用来连接 TDengine 集群完成数据存储、查询以及其他功能。TDengine 客户端驱动的 API 类似于 MySQL 的 C API。…...
什么是混合搜索Hybrid Search?
🧠 向所有学习者致敬! “学习不是装满一桶水,而是点燃一把火。” —— 叶芝 我的博客主页: https://lizheng.blog.csdn.net 🌐 欢迎点击加入AI人工智能社区! 🚀 让我们一起努力,共创AI未来! 🚀 混合搜索通常指一种结合多种搜索方法或技术的搜索策略,旨在提供更…...
滤波器:模拟滤波器和数字滤波器的区别
滤波器是一种用于从信号中去除不需要的频率成分,只保留所需频率成分的电子设备或算法。根据实现方式的不同,滤波器主要分为模拟滤波器和数字滤波器两大类。以下是对这两种滤波器的详细比较: 一、实现方式与原理 模拟滤波器 实现方式…...
AudioRecord 录制pcm转wav
pcm转wav PCM 格式校验pcm 添加 wav 头信息WAVWAV 格式检验小端序? 参考地址 PCM 格式校验 /*** 专业PCM文件验证(支持动态参数与多格式)* param silenceThreshold 静音检测阈值(0.0~1.0),默认90%零值为静…...
625SJBH网上便利店的设计与实现
1前 言 目前,网络正以一种前所未有的冲击力在影响着人类的活动,包括人类的生产和日常生活。网络的诞生和发展,颠覆了传统的信息传播方式,冲破了存在于传统交流方式中时间和空间的种种壁垒,极大地改变了人类从物质到精…...
如何开发英语在线训练小程序:从0到1的详细步骤
在数字化学习的浪潮下,英语在线训练小程序凭借便捷、高效的学习模式,成为众多英语学习者的得力助手。如果你也想开发一款独具特色的英语在线训练小程序,不妨参考以下步骤,开启你的小程序开发之旅。 一、前期规划 (…...
java设计模式-装饰者模式
装饰者模式(Decorator) 定义 1、动态的将新功能附加到对象上,在对象功能扩展方面,他比继承更有弹性,也体现了开闭原则(OCP) 2、这里提到的动态的将新功能附加到对象和OCP原则,在后面应用实际上会以代码的形式体现。 //饮料 // 饮…...
我提了一个 Androidx IssueTracker
问题 在运行 gradle plugin 插件的 transform R8 阶段出现了报错 Caused by: com.android.tools.r8.internal.xk: java.lang.NullPointerException: Cannot invoke “String.length()” because “” is null 报错日志 FAILURE: Build failed with an exception.* What went w…...
spring mvc @ResponseBody 注解转换为 JSON 的原理与实现详解
ResponseBody 注解转换为 JSON 的原理与实现详解 1. 核心作用 ResponseBody 是 Spring MVC 的一个注解,用于将方法返回的对象直接序列化为 HTTP 响应体(如 JSON 或 XML),而不是通过视图解析器渲染为视图(如 HTML&…...
RK3588芯片NPU的使用:Windows11 Docker中运行MobileNet模型以及部署到开发板进行目标检测
本文的目标 本文将在RKNN Docker环境(见本系列的第二篇文章)中练习MobileNet图像分类示例,并通过adb工具部署到RK3588开发板。 MobileNet简介请参考上一篇文章。 开发环境说明 主机系统:Windows11目标设备:搭载RK35…...
智能仓储数字孪生Demo(Unity实现)
一、项目背景与行业痛点 医药流通行业仓储管理面临三大核心挑战: 合规性风险:GSP(药品经营质量管理规范)对温湿度、药品批次追溯的严苛要求,传统人工记录易出错效率瓶颈:库区布局复杂,人工巡检…...
Qt上hook钩子的使用,监测键盘和鼠标。
演示平台:windows。 编译环境:Qt5.12.2 MinGW 64-bit Windows API: ///加载钩子 /*** SetWindowsHookEx 函数解释* int idHook 所监控的挂钩类型* HOOKPROC lpfn 监控信息的处理函数* HINSTANCEhMod 监控信息的动态链接位置 nullptr则与本线…...
Android12源码编译之预置Android Studio项目Android.mk文件编写
1、在AndroidManifest.xml文件中添加package"com.sprd.silentinstalldemo"属性,因为新版本的Android Studio默认生成的AndroidManifest.xml是没有这个属性值的 <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:an…...
微服务注册中心选择指南:Eureka vs Consul vs Zookeeper vs Nacos
文章目录 引言微服务注册中心概述什么是服务注册与发现选择注册中心的标准 常见的微服务注册中心1. Eureka1.1 理论基础1.2 特点1.3 示例代码 2. Consul2.1 理论基础2.2 特点2.3 示例代码 3. Zookeeper3.1 理论基础3.2 特点3.3 示例代码 4. Nacos4.1 理论基础4.2 特点4.3 示例代…...
pg_waldump无法定位WAL文件问题
目录 排查pg_waldump无法定位WAL文件问题的步骤1. 确认WAL文件路径配置2. 检查WAL文件名格式3. 验证文件存在性4. 检查文件权限5. 时间线历史文件检查6. 使用pg_controldata验证状态7. 尝试指定完整路径 典型错误场景及解决方案 排查pg_waldump无法定位WAL文件问题的步骤 1. 确…...
Mysql安装
Mysql安装 1. windows安装1.1 官网下载1.2 安装 1. windows安装 1.1 官网下载 官网下载 选择对于版本,然后跳转到下载页 1.2 安装...
Windows版-RabbitMQ自动化部署
一键完成Erlang环境变量配置(ERLANG_HOME系统变量) 一键完成RabbitMQ环境变量配置(RabbitMQ系统变量) 实现快速安装部署RabbitMQ PS: 需提前下载安装: - otp_win64_25.0.exe (Erlang) - rabbit…...
spring mvc的拦截器HandlerInterceptor 接口详解
HandlerInterceptor 接口详解 1. 接口方法说明 方法作用执行时机返回值/注意事项preHandle请求处理前拦截在控制器方法执行前调用返回 false 中断后续流程;返回 true 继续执行postHandle控制器方法执行后拦截在控制器方法返回结果后,视图渲染前调用无返…...