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

使用lldb查看Rust不同类型的结构

目录

前言

正文

标量类型

复合类型——元组

 复合类型——数组

函数

&str

struct

可变数组vec

Iter

String

Box

Rc

Arc

 RefCell

Mutex

RwLock

Channel

总结


前言

笔者发现这个lldb挺好玩的,可以查看不同类型的结构,虽然这好像是C++的东西,

看看Rust的也可以,

笔者使用RustRover中的调试模式,在后面的代码,在打印语句哪一行打断点。

输出使用

expr    <变量>

正文

参考如下

数据类型 - Rust 程序设计语言 中文版Rust 程序设计语言中文也译为 Rust 权威指南,是 Rust 官方推出的学习 Rust 的必备教程。Rust Wiki 版的 Rust 程序设计语言简体中文版将由 Rust 中文翻译项目组持续维护和更新,确保内容最新最全。https://www.rustwiki.org.cn/zh-CN/book/ch03-02-data-types.html

标量类型

标量scalar)类型表示单个值。Rust 有 4 个基本的标量类型:整型、浮点型、布尔型和字符

比如

    let a=1;println!("{a}")

输出

(lldb) expr a
(i32) a = 1

i32表示是32为的整数,当前值为1

获取其地址

(lldb) expr &a
(*mut i32) &a = 0x000000839274f5f4

加个引用符号。

对于其他类似的,比如u32,u8、true等,这些标量类型都是放在某一个地址中,没有其他东西。

使用其他命令——frame variable -L

(lldb) frame variable -L a0x000000d6151df964: (i32) a = 1

可以看到输出了地址、类型、变量、值。

在tauri中没有什么区别。

复合类型——元组

看看元组内部长什么样的

比如

    let a=(1,2.0,'g');println!("{a:?}")

输出

(lldb) expr a
(tuple$<i32,f64,char>) a = (__0 = 1, __1 = 2, __2 = 'g')

可以使用 .0或者__0访问其中的数据

(lldb) expr a.__0
(i32) __0 = 1
(lldb) expr a.0
(i32) __0 = 1

看来这个元组是多个标量和在一起的类型

在rust代码中,无法使用 __0

类型 `(i32, f64, char)` 中没有字段 `__0` [E0609]

 在tauri中没有什么区别。

 复合类型——数组

    let a=[1,2,3];println!("{a:?}")

输出

(lldb) expr a
([i32; 3]) a = ([0] = 1, [1] = 2, [2] = 3)

这里是i32类型,长度为3的数组。

在lldb访问其中的值,可以使用a[0],也可以使用a.0

(lldb) expr a[0]
(i32) [0] = 1
(lldb) expr a.0
(i32) [0] = 1

函数

如果是一个函数

fn f1()->i32{return 1; 
}
fn main() {let a=f1;println!("123");}

a会是什么? 输出看看

(lldb) expr a
(*mut ) a = 0x0000000011117b00

*mut 表示是一个可变的指针

笔者想调用a,但是没成功

(lldb) expr a()
error: function call failed

不知道什么情况。

&str

    let x="abc";println!("{x}");

换个字母。

看看&str的在lldb的输出

(lldb) expr x
(ref$<str$>) x = "abc" {data_ptr = 0x00007ff791a1a3b0length = 3
}

有两个东西,笔者都不知道改怎么称呼,就叫 字段,

有两个字段,一个data_ptr,显而易见,是存放数据的地址,可以修改

另一个length,就是长度了。

进去地址看看

(lldb) expr x.data_ptr
(*mut u8) data_ptr = 0x00007ff791a1a3b0

 发现又是是个可变指针,指向一个u8类型的内存地址

可以加个*访问了

(lldb) expr *(x.data_ptr)
(u8) *data_ptr = 97

发现是97,这不就是a的ASCLL码,

访问一下其他的

(lldb) expr *x.data_ptr+1
(u32)  = 98
(lldb) expr *x.data_ptr+2
(u32)  = 99

没问题。

笔者本来想修改数据的,没想到失败了

(lldb) memory region x.data_ptr
[0x00007ff688860000-0x00007ff688883000) r--

memory region 是 LLDB 调试器中的一个命令,

用于显示指定内存地址所在的内存区域的属性和权限信息。

它会告诉你某个地址是否可读、可写、可执行,以及该内存区域的起始和结束范围。

可以发现,只有r,只有只读

笔者就算在变量设置mut,内存还是还是只读

但是,可以修改长度

(lldb) expr (x).length=1
(u64) length = 1

总之,这个&str就像一个“结构体”,感觉不是很准确,应该说像“json”。

笔者发现tauri 通信函数greet

#[command]
fn greet(name: &str) -> String {println!("Hello, {}!", name);format!("Hello, {}! You've been greeted from Rust!", name)
}

这个name,内存居然拥有写的权限

(ref$<str$>) name = "world" {data_ptr = 0x000001b36114b6f0length = 5
}
(lldb) memory region 0x000001b36114b6f0
[0x000001b361050000-0x000001b36114f000) rw-

笔者不能理解 

struct

看看结构体

如下,

    struct book<'a>{id: i32,name:&'a str,}let book1 = book{id: 1,name: "rust",};println!("{}", book1.name);

输出

(lldb) expr book1
(shared_state_concurrency::main::book) book1 = {id = 1name = "rust" {data_ptr = 0x00007ff7d53fa3b0length = 4}
}

真像json,比如取值——length

(lldb) expr book1.name.length
(u64) length = 4

没问题

可变数组vec

    let a=vec![1, 2, 3];println!("{:?}", a);

输出

(lldb) expr a
(alloc::vec::Vec<i32,alloc::alloc::Global>) a = size=3 {[0] = 1[1] = 2[2] = 3
}

获取第一个字段——buf,a.0、a[0]、或者a.buf,都行

(lldb) expr a.buf
(alloc::raw_vec::RawVec<i32,alloc::alloc::Global>) buf = {inner = {ptr = {pointer = {pointer = 0x000002b284ccfc20}_marker = {}}cap = (__0 = 3)alloc = {}}_marker = {}
}

看看这个地址可不可以写

(lldb) memory region 0x000002b284ccfc20
[0x000002b284cb0000-0x000002b284cd0000) rw-

 发现有w,可以写,改成66 77 88。

修改数据

memory write -s 4 0x000001d9e06a7430 42 4d 58

因为是i32类型的,32位,需要4个字节,

66是十进制,变成16进制是42

其他同理。写完后

(lldb) expr a(alloc::vec::Vec<i32,alloc::alloc::Global>) a = size=3 {[0] = 66[1] = 77[2] = 88
}

没问题

Iter

看看迭代器

    let a=vec![1,2,3];let iter= a.iter();println!("{a:?}")

如果以json数据表示iter的结构,如下

{"iter": {"ptr": {"pointer": "0x000001dd45d299f0"},"end_or_len": "0x000001dd45d299fc","_marker": {}}
}

发现这个iter,pointer和 end_or_len都是地址,

意思就很明显了,从pointer开始,到end_or_len结束。

f0到fc ,中间有12个字节,类型是i32的,没问题。

String

    let a=String::from("hello");println!("{:?}", a);

输出

(lldb) expr a
(alloc::string::String) a = "hello" {vec = size=5 {[0] = 104[1] = 101[2] = 108[3] = 108[4] = 111}
}

可以看到String里面放了一个vec,

(lldb) expr a.vec
(alloc::vec::Vec<u8,alloc::alloc::Global>) vec = size=5 {[0] = 104[1] = 101[2] = 108[3] = 108[4] = 111
}

这个vec元素的类型还是u8。

如果考虑成json结构,可能是这样的

{"a":{"vec": {"buf": {"inner": {"ptr": {"pointer": {"pointer": "0x000001651effdeb0"},"_marker": {}},"cap": {"__0": 5},"alloc": {}},"_marker": {}},"len": 5}}
}

没问题

Box

Box是智能指针,允许将一个值放在堆上而不是栈上

    let a=Box::new(1);println!("{:?}", a);

输出,看看a长什么样

(lldb) expr a
(*mut i32) a = 0x00000279d903de90

确实是一个指针

获取其中的值*a

(lldb) memory region 0x00000279d903de90
error: 'jb_renderers_set_markup' is not a valid command.
[0x00000279d9030000-0x00000279d9050000) rw-

有写的权限 

Rc

Rc被称为 引用计数

    let a=Rc::new(1);println!("{:?}", a);

输出 

(lldb) expr  a
(alloc::rc::Rc<i32,alloc::alloc::Global>) a = strong=1, weak=0 {value = 1
}

这个Rc就比Box要复杂的得多

使用json表示内部的结构

{"a:rc":{"ptr": {"pointer":{"strong":{"value": {"value": 1}},"weak":{"value": {"value": 1}},"value":1}},"phantom":{},"alloc": {}}
}

表示的不是很准确,因为pointer其实是一个指针。

(lldb) expr a.ptr.pointer
(*mut alloc::rc::RcInner<i32>) pointer = 0x000001eb490a7710

拥有写的权限


(lldb) memory region 0x000001eb490a7710
[0x000001eb49090000-0x000001eb490b0000) rw-

使用一次clone,

let b=Rc::clone(&a);

发现strong变成了2

(lldb) expr a.ptr.pointer.strong.value.value
(u64) value = 2

Arc

Arc原子引用计数指针,可以安全地在多线程环境中共享数据

结构和Rc几乎一模一样,但是其中的类型不一样。笔者就不展示了

 RefCell

允许你即使在有不可变引用时也可以改变数据

    let a=RefCell::new(1);println!("{:?}", a);

输出用json表示

  "a:RefCell":{"value": {"value": 1},"borrowed": {"value": {"value": 0}}}

这个RefCell 有点高级,笔者没有看到关于地址的东西

使用一下

    {let mut b=a.borrow_mut();*b=2;println!("{:?}", a);}

在大括号里面,发现这个a的borrow的值

(lldb) expr a.borrow.value.value
(i64) value = -1

居然变成了-1,有点意思

Mutex

看看互斥锁

    let a=Mutex::new(1);println!("{a:?}")

输出,用json表示结构

{"a:Mutex":{"inner": {"futex": {"v": {"value": 0}}},"poison": {"failed": {"v": {"value": 0}}},"data": {"value": 1}}
}

如果使用了lock

let lock=a.lock().unwrap();

可以发现futex的值变成了1

(lldb) expr a.inner.futex.v.value
(u8) value = 1

RwLock

    let a=RwLock::new(1);println!("{a:?}")

其结构用json表示

{"a:RwLock": {"inner": {"state": {"v": {"value": 0}},"writer_notify": {"v": {"value": 0}}},"poison": {"failed": {"v": {"value": 0}}},"data": {"value": 1}}
}

和Mutex差不多,但是inner内部变了

很容易猜测,使用一次读锁,state对应的值变成1

使用一次写锁writer_notify对应的值变成1

但是,笔者使用读锁,确实如下

 let b=a.read().unwrap();
(lldb) expr a.inner.state.v.value
(u32) value = 1

使用写锁

let mut b=a.write().unwrap();

发现并不是writer_notify变成1

(lldb) expr a
(std::sync::poison::rwlock::RwLock<i32>) a = {inner = {state = {v = (value = 1073741823)}writer_notify = {v = (value = 0)}}poison = {failed = {v = (value = 0)}}data = (value = 1)
}

而是这个state变成了一个很大的值,1073741823,这个值感觉不是巧合,笔者不能理解。

写锁是独占的。

笔者添加4个读锁,发现state对应的值变成了4

看来根据这个state的值可以判断是读锁还是写锁。具体实现笔者不是很清楚,必然和state有很大的关系。

Channel

看看通道

use std::sync::mpsc::channel;
use std::thread;
fn main() {let (tx, rx) = channel();thread::spawn(move || {let val = String::from("hi");tx.send(val).unwrap();});println!("123")
}

tx 和rx用json表示

{"tx": {"inner": {"flavor": {"0": {"counter": "0x0000020b23389b00"}}}},"rx": {"inner": {"flavor": {"0": {"counter": "0x0000020b23389b00"}}}}
}

可以发现,二者的结构是一模一样的。最后都指向一个地址。

 意思就显而易见了,把某个消息传递到某个地址,然后再从这个地址中获取消息

这就是通道吗?有点意思。

总结

看了看,rust的不同类型的结构

感觉这个结构,无论是什么,好像都可以用json表示。有点意思

相关文章:

使用lldb查看Rust不同类型的结构

目录 前言 正文 标量类型 复合类型——元组 复合类型——数组 函数 &str struct 可变数组vec Iter String Box Rc Arc RefCell Mutex RwLock Channel 总结 前言 笔者发现这个lldb挺好玩的&#xff0c;可以查看不同类型的结构&#xff0c;虽然这好像是C的东…...

【Linux】线程POSIX信号量

目录 1. 整体学习思维导图 2. 信号量的概念 3. 基本接口 4. 基于环形队列的生产者消费者模型(信号量) 1. 整体学习思维导图 2. 信号量的概念 POSIX信号量和SystemV信号量作用相同&#xff0c;都是用于同步操作&#xff0c;达到无冲突的访问共享资源目的。但 POSIX可以用于线…...

WPF中如何自定义控件

WPF自定义控件简化版&#xff1a;账户菜单按钮&#xff08;AccountButton&#xff09; 我们以**“账户菜单按钮”为例&#xff0c;用更清晰的架构实现一个支持标题显示、渐变背景、选中状态高亮**的自定义控件。以下是分步拆解&#xff1a; 一、控件核心功能 我们要做一个类似…...

大模型MCP更高效的通信:StreamableHTTP协议

随着大语言模型&#xff08;LLMs&#xff09;的飞速发展&#xff0c;模型与应用之间的通信效率和灵活性变得至关重要。Model Context Protocol (MCP) 作为专为模型交互设计的协议&#xff0c;一直在不断进化以满足日益增长的需求。近期&#xff0c;MCP引入了一个令人振奋的新特…...

防火墙在网络安全体系中的核心作用与原理

防火墙在网络安全体系中的核心作用与原理 一、核心作用解析 1. 访问控制中枢 功能维度实现方式典型场景黑白名单控制基于IP/端口/协议的规则过滤限制外部IP访问财务系统&#xff0c;仅开放VPN端口权限分级用户组策略映射&#xff08;如AD集成&#xff09;禁止普通员工访问核心…...

MySQL事务和JDBC中的事务操作

一、什么是事务 事务是数据库操作的最小逻辑单元&#xff0c;具有"全有或全无"的特性。以银行转账为例&#xff1a; 典型场景&#xff1a; 从A账户扣除1000元 向B账户增加1000元 这两个操作必须作为一个整体执行&#xff0c;要么全部成功&#xff0c;要么全部失败…...

每日脚本学习5.10 - XOR脚本

xor运算的简介 异或就是对于二进制的数据可以 进行同0异1 简单的演示 &#xff1a; 结果是 这个就是异或 异或的作用 1、比较两数是否相等 2、可以进行加密 加密就是需要key 明文 :0b010110 key : 0b1010001 这个时候就能进行加密 明文 ^ key密文 还有这个加密比…...

【编译原理】总结

核心 闭包&#xff0c;正则闭包 产生式&#xff08;规则&#xff09; 文法 G[S](&#xff0c;&#xff0c;P&#xff0c;S) 一组规则的集合 &#xff1a;非终结符 &#xff1a;终结符 P&#xff1a;产生式 S&#xff1a;开始符号 推导 归约 规范&#xff08;最右&#xff…...

docker创建一个centOS容器安装软件(以宝塔为例)的详细步骤

备忘&#xff1a;后续偶尔忘记了docker虚拟机与宿主机的端口映射关系&#xff0c;来这里查看即可&#xff1a; docker run -d \ --name baota \ --privilegedtrue \ -p 8888:8888 \ -p 8880:80 \ -p 8443:443 \ -p 8820:20 \ -p 8821:21 \ -v /home/www:/www/wwwroot \ centos…...

OpenVLA:开源的视觉-语言-动作模型

1. 简介 让我们先来介绍一下什么是OpenVLA&#xff0c;在这里&#xff1a; https://openvla.github.io/ 可以看到他们的论文、数据、模型。 OpenVLA 是一个拥有 70亿参数的开源 **视觉-语言-动作&#xff08;VLA&#xff09;**模型。它是在 Open X-Embodiment 数据集 中的 97万…...

Matlab/Simulink的一些功能用法笔记(4)

水一篇帖子 01--MATLAB工作区的保护眼睛颜色设置 默认的工作区颜色为白色 在网上可以搜索一些保护眼睛的RGB颜色参数设置 在MATLAB中按如下设置&#xff1a; ①点击预设 ②点击颜色&#xff0c;点击背景色的三角标符号 ③点击更多颜色&#xff0c;找到RGB选项 ④填写颜色参数…...

【比赛真题解析】混合可乐

这次给大家分享一道比赛题:混合可乐。 洛谷链接:U561549 混合可乐 【题目描述】 Jimmy 最近沉迷于可乐中无法自拔。 为了调配出他心目中最完美的可乐,Jimmy买来了三瓶不同品牌的可乐,然后立马喝掉了一些(他实在是忍不住了),所以 第一瓶可口可乐最大容量为 a 升,剩余 …...

Elasticsearch:我们如何在全球范围内实现支付基础设施的现代化?

作者&#xff1a;来自 Elastic Kelly Manrique SWIFT 和 Elastic 如何应对基础设施复杂性、误报问题以及日益增长的合规要求。 金融服务公司在全球范围内管理实时支付方面面临前所未有的挑战。SWIFT&#xff08;Society for Worldwide Interbank Financial Telecommunication -…...

matlab介绍while函数

MATLAB 中的 while 语句介绍 在 MATLAB 中&#xff0c;while 语句是一种循环结构&#xff0c;用于在满足特定条件时反复执行一段代码块。与 for 循环不同&#xff0c;while 循环的执行次数是动态的&#xff0c;取决于循环条件是否为真。 语法 while condition% 循环体代码 e…...

如何解决 PowerShell 显示 “此系统上禁用了脚本运行” 的问题

在 Windows 11 或 10 的 PowerShell 中运行脚本时,你可能会遇到一个错误,提示系统上禁用了脚本运行。这是一种安全功能,而不是系统问题,旨在防止可能有害的脚本自动运行。然而,如果你需要运行脚本来完成某些任务,或者你在系统上做了软件开发或测试的环境,那么你需要在 P…...

深入浅出之STL源码分析4_类模版

1.引言 我在上面的文章中讲解了vector的基本操作&#xff0c;然后提出了几个问题。 STL之vector基本操作-CSDN博客 1.刚才我提到了我的编译器版本是g 11.4.0&#xff0c;而我们要讲解的是STL&#xff08;标准模板库&#xff09;&#xff0c;那么二者之间的关系是什么&#x…...

探索科技的前沿动态:科技爱好者周刊

探索科技的前沿动态:科技爱好者周刊 在信息爆炸的时代,我们每时每刻都被新技术、新理念包围。而如何在这纷繁复杂的信息中找到对自己有价值的内容,成了一大挑战。今天,我们要介绍的是一个宝贵的资源——科技爱好者周刊,它致力于为科技爱好者提供优质的科技资讯,每周五发…...

初学者入门指南:什么是网络拓扑结构?

初学者入门指南&#xff1a;什么是网络拓扑结构&#xff1f; 在构建或学习计算机网络时&#xff0c;一个绕不开的核心概念便是“网络拓扑结构”&#xff08;Network Topology&#xff09;。它决定了网络中各个设备如何连接、通信以及如何扩展。理解网络拓扑不仅有助于我们更清…...

在 Vue 3 中实现刮刮乐抽奖

&#x1f389; 在 Vue 3 中实现刮刮乐抽奖 当项目中需要做一些活动互动页时&#xff0c;需要实现刮刮乐&#xff0c;请看如下效果&#xff1a; 这里感谢github用户Choicc分享的组件&#xff0c;具体可点击传送门查看 1. 引入组件 将/src/components下ScratchCard.vue复制到自…...

Satori:元动作 + 内建搜索机制,让大模型实现超级推理能力

Satori&#xff1a;元动作 内建搜索机制&#xff0c;让大模型实现超级推理能力 论文大纲一、背景&#xff1a;LLM 推理增强的三类方法1. 基于大规模监督微调&#xff08;SFT&#xff09;的推理增强2. 借助外部机制在推理时进行搜索 (RLHF / 多模型 / 工具)3. 现有局限性总结 二…...

SDC命令详解:使用all_outputs命令进行查询

相关阅读 SDC命令详解https://blog.csdn.net/weixin_45791458/category_12931432.html all_outputs命令用于创建一个输出端口对象集合&#xff0c;关于设计对象和集合的更详细介绍&#xff0c;可以参考下面的博客。 Synopsys&#xff1a;设计对象https://chenzhang.blog.csdn…...

printf调试时候正常,运行时打印不出来

问题是在添加了 printf 功能后&#xff0c;程序独立运行时无法正常打印输出&#xff0c;而调试模式下正常。这表明问题可能与 printf 的重定向实现、标准库配置、或编译器相关设置有关。 解决&#xff1a; 原来是使用 Keil/IAR&#xff0c;printf可能需要启用 MicroLIB 或正确…...

解决 TimeoutError: [WinError 10060] 在 FramePack项目中连接 Hugging Face 超时的问题

#工作记录 以下是针对 TimeoutError: [WinError 10060] 的完整排查方案&#xff0c;适用于 FramePack项目中。 &#xff08;一般该错误的发生原因请重点排查Hugging Face模型仓库受限需要登录的情形&#xff09; FramePack项目参考资料 FramePack部署&#xff08;从PyCharm解…...

分布式-Redis分布式锁

Redis实现分布式锁优点 &#xff08;1&#xff09;Redis有很高的性能&#xff1b; &#xff08;2&#xff09;Redis命令对此支持较好&#xff0c;实现起来比较方便 实现思路 &#xff08;1&#xff09;获取锁的时候&#xff0c;使用setnx加锁&#xff0c;并使用expire命令为锁…...

UniRepLknet助力YOLOv8:高效特征提取与目标检测性能优化

文章目录 一、引言二、UniRepLknet 的框架原理&#xff08;一&#xff09;架构概述&#xff08;二&#xff09;架构优势 三、UniRepLknet 在 YOLOv8 中的集成&#xff08;一&#xff09;集成方法&#xff08;二&#xff09;代码实例 四、实验与对比&#xff08;一&#xff09;对…...

自研时序大模型讲解(4月29日)直播回顾

4 月 29 日&#xff0c;清华团队揭秘&#xff1a;时序大模型如何让数据“活”起来线上直播圆满结束。清华大学软件学院博士生&#xff0c;IoTDB 原生机器学习引擎 AINode 研发同学刘雍在线上面向数千人次的时序数据分析人员与 AI 大模型行业关注者&#xff0c;就时序大模型的发…...

The Action Replay Process

Preface A commonly used inequality − x > ln ⁡ ( 1 − x ) , 0 < x < 1 -x > \ln(1 - x), \quad 0 < x < 1 −x>ln(1−x),0<x<1 Proof: Let f ( x ) ln ⁡ ( 1 − x ) x f(x) \ln(1 - x) x f(x)ln(1−x)x, for 0 < x < 1 0 < …...

k8s之ingress解释以及k8s创建业务的流程定义

matchLabels ingress Ingress 是反向代理规则&#xff0c;用来规定 HTTP/S 请求应该被转发到哪个 Service 上&#xff0c;比如根据请求中不同的 Host 和 url 路径让请求落到不同的 Service 上。 Ingress Controller 就是一个反向代理程序&#xff0c;它负责解析 Ingress 的反向…...

LVGL对象的盒子模型和样式

文章目录 &#x1f9f1; LVGL 对象盒子模型结构&#x1f50d; 组成部分说明&#x1f3ae; 示例代码&#x1f4cc; 总结一句话 &#x1f9f1; 一、样式的本质&#xff1a;lv_style_t 对象&#x1f3a8; 二、样式应用的方式&#x1f9e9; 三、样式属性分类&#xff08;核心&#…...

从0开始学习大模型--Day05--理解prompt工程

提示词工程原理 N-gram&#xff1a;通过统计&#xff0c;计算N个词共同出现的概率&#xff0c;从而预测下一个词是什么。 深度学习模型&#xff1a;有多层神经网络组成&#xff0c;可以自动从数据中学习特征&#xff0c;让模型通过不断地自我学习不断成长&#xff0c;直到模型…...