从C/C++踩坑到Rust优雅避雷:内存安全转型全指南

第一章:从C/C++到Rust:内存安全转型的必然之路

在系统级编程领域,C 和 C++ 长期占据主导地位,其高性能与底层控制能力备受青睐。然而,伴随这种自由而来的是沉重的内存管理负担。悬空指针、缓冲区溢出、数据竞争等问题频繁引发安全漏洞,成为现代软件开发中的重大隐患。Rust 的出现,正是为了解决这一根本性挑战,在不牺牲性能的前提下,通过创新的所有权(ownership)和借用(borrowing)机制,实现内存安全的静态保障。

内存安全问题的根源

C/C++ 允许开发者直接操作内存,但缺乏编译时的安全检查。例如,以下代码在 C 中是合法的,却极易导致未定义行为:

int* create_dangling() {
    int local = 42;
    return &local; // 返回局部变量地址,产生悬空指针
}
Rust 编译器则在编译阶段阻止此类错误:

fn create_dangling() -> &i32 {
    let x = 42;
    &x // 编译错误:`x` 不会存活到返回时
}

Rust 的核心优势

Rust 通过以下机制确保内存安全:
  • 所有权系统:每个值有唯一所有者,作用域结束时自动释放
  • 借用检查:引用必须始终有效,禁止悬空指针
  • 生命周期标注:显式声明引用的存活周期,由编译器验证
特性C/C++Rust
内存泄漏常见,需手动管理编译器警告,可检测
数据竞争运行时风险编译时禁止
性能开销无运行时开销零成本抽象
graph TD A[源代码] --> B[Rust 编译器] B --> C{所有权检查} C -->|通过| D[安全可执行文件] C -->|失败| E[编译错误提示]
这种设计使得 Rust 在操作系统、嵌入式系统和高性能服务等场景中逐步替代 C/C++,成为构建可靠系统的首选语言。

第二章:Rust内存安全核心机制解析

2.1 所有权系统:内存管理的全新范式

Rust 的所有权系统彻底改变了传统内存管理方式,无需垃圾回收器即可保证内存安全。每个值都有唯一的所有者,当所有者离开作用域时,值自动被释放。
核心规则
  • 每个值在同一时刻只能有一个所有者
  • 当所有者超出作用域,值将被自动清理
  • 值的赋值或传递会转移所有权,而非复制
代码示例

fn main() {
    let s1 = String::from("hello"); // s1 拥有内存资源
    let s2 = s1;                    // 所有权转移至 s2
    // println!("{}", s1);         // 错误!s1 已失效
    println!("{}", s2);             // 正确:s2 是当前所有者
}
上述代码中,s1 创建一个堆上字符串,赋值给 s2 时发生“移动”(move),s1 不再有效,防止了数据竞争与双重释放。
内存布局示意
栈: [s2] → 堆: "hello"
s1 移动后失效,仅 s2 可访问堆内存。

2.2 借用与引用:安全访问的数据规则

在Rust中,借用(borrowing)机制允许函数临时访问数据而无需取得所有权,从而避免不必要的复制开销。通过引用(&T),我们可以创建对值的只读或可变访问。
不可变与可变引用

fn main() {
    let s = String::from("hello");
    let len = calculate_length(&s); // 不可变引用
    println!("长度为: {}", len);
}

fn calculate_length(s: &String) -> usize {
    s.len() // s 被借用,不能修改
}
上述代码中,&s 创建了对 s 的不可变引用,函数可读取但不能修改其内容。引用不拥有数据,因此生命周期结束后不会调用 drop。 若需修改,可使用可变引用 &mut T,但同一作用域内对同一数据的可变引用有且仅有一个,防止数据竞争。
借用规则总结
  • 任意时刻,只能拥有一个可变引用或多个不可变引用之一;
  • 引用必须始终指向有效内存,不允许悬垂引用;
  • 引用的生命周期不得超出其所指向数据的生命周期。

2.3 生命周期标注:消除悬垂指针的编译时保障

在Rust中,生命周期标注是确保引用安全的核心机制。它通过编译时分析引用的有效期,防止悬垂指针的产生。
生命周期的基本语法

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() { x } else { y }
}
该函数声明了泛型生命周期参数 'a,表示输入和返回的引用至少在相同生命周期内有效。编译器据此验证所有引用在使用期间均未超出其作用域。
常见生命周期场景
  • &str 引用必须绑定到明确的生命周期
  • 结构体中包含引用时,需为每个引用字段指定生命周期
  • 多个引用参与计算时,编译器推导最小公共生命周期
通过静态分析,Rust在不牺牲性能的前提下,彻底杜绝了运行时因悬垂指针引发的内存错误。

2.4 栈上分配与零成本抽象的性能优势

栈上分配的机制
在现代编译器优化中,栈上分配通过将对象存储在调用栈而非堆中,显著减少内存管理开销。局部变量和小型结构体通常被直接分配在栈帧内,函数返回时自动回收。

fn compute_sum(arr: [i32; 1000]) -> i32 {
    let mut sum = 0;
    for &val in &arr {
        sum += val;
    }
    sum
}
上述代码中,数组 arr 和变量 sum 均位于栈上。无需动态分配,避免了 malloc 或垃圾回收的延迟。
零成本抽象的实现原理
Rust 和 C++ 等语言支持零成本抽象,即高级语法结构(如迭代器)在编译后不引入运行时开销。编译器通过内联和单态化消除抽象层。
  • 迭代器链被编译为裸循环
  • 泛型实例生成专用机器码
  • 闭包转换为函数指针或内联代码

2.5 不可变性默认策略对并发安全的深远影响

在现代编程语言设计中,不可变性(Immutability)正逐渐成为默认的数据管理策略。这种范式转变显著提升了并发程序的安全性,从根本上规避了数据竞争问题。
不可变对象的线程安全性
一旦对象被创建后其状态无法更改,多个线程同时访问时无需额外同步机制。例如,在 Go 中定义只读结构体:

type Config struct {
    Timeout int
    Host    string
}

// 工厂函数确保初始化后不可变
func NewConfig(timeout int, host string) *Config {
    return &Config{Timeout: timeout, Host: host}
}
该实例一经构造便不可修改,所有字段为只读,天然支持多线程安全访问。
与并发模型的协同效应
  • 消除锁竞争,降低死锁风险
  • 简化内存模型,提升编译器优化空间
  • 支持高效共享,避免深拷贝开销
不可变性通过约束状态变更路径,使并发逻辑更可预测,是构建高可靠系统的重要基石。

第三章:常见C/C++内存陷阱及Rust对应解决方案

3.1 悬垂指针:Rust如何在编译期拦截非法访问

悬垂指针是指指向已释放内存的指针,C/C++中此类问题常导致运行时崩溃。Rust通过所有权和借用检查机制,在编译期静态分析内存生命周期,从根本上杜绝此类错误。
所有权与借用规则
Rust规定每个值有且仅有一个所有者,当所有者离开作用域时资源被自动释放。引用必须始终有效,编译器通过借用检查器验证引用的合法性。

fn main() {
    let r;                // ---+
    {                     //    |
        let x = 5;        //    | x 的作用域
        r = &x;           //    | 错误:x 将被释放,r 成为悬垂引用
    }                     // ---+
    println!("{}", r);    // 编译错误!
}
上述代码无法通过编译,因为 r 引用了已销毁的变量 x。Rust编译器会标记出该生命周期违规。
生命周期标注示例
函数返回引用时,需明确标注生命周期,确保返回引用不超出其指向数据的存活期:

fn longest<'a>(s1: &'a str, s2: &'a str) -> &'a str {
    if s1.len() > s2.len() { s1 } else { s2 }
}
此处 'a 表示输入与输出引用的生命周期必须至少一样长,编译器据此验证安全性。

3.2 缓冲区溢出:边界检查与安全集合类型实践

缓冲区溢出是C/C++等低级语言中常见的安全漏洞,源于程序向固定长度的缓冲区写入超出其容量的数据,导致覆盖相邻内存区域。现代高级语言通过引入边界检查机制有效缓解此类风险。
边界检查的运行时保障
以Go语言切片为例,访问元素时自动触发边界检查:

package main

func main() {
    arr := make([]int, 5)
    arr[10] = 42 // 触发 panic: runtime error: index out of range
}
该代码在运行时抛出索引越界异常,防止非法内存写入。编译器在数组访问前后插入检查逻辑,确保下标在 [0, len) 范围内。
安全集合类型的工程实践
推荐使用具备内置防护的集合类型,如Java的 ArrayList 或Rust的 Vec,它们结合动态扩容与边界校验,在性能与安全间取得平衡。

3.3 资源泄漏:RAII与Drop trait的自动清理机制

RAII:资源获取即初始化
在系统编程中,资源泄漏是常见隐患,如文件句柄、内存或网络连接未正确释放。Rust 采用 RAII(Resource Acquisition Is Initialization)模式,在对象构造时获取资源,析构时自动释放。
Drop trait 的自动清理
Rust 通过 Drop trait 实现自动清理。任何实现了 Drop 的类型,其 drop(&mut self) 方法会在变量离开作用域时被自动调用。

struct FileHandle {
    name: String,
}

impl Drop for FileHandle {
    fn drop(&mut self) {
        println!("释放文件资源: {}", self.name);
    }
}

{
    let f = FileHandle { name: "config.txt".to_string() };
} // f 离开作用域,自动调用 drop
上述代码中,FileHandle 在作用域结束时自动释放资源,无需手动调用清理函数,有效防止资源泄漏。该机制结合所有权系统,确保每个资源仅被释放一次,且必定被释放。

第四章:实战中的内存安全模式与最佳实践

4.1 使用Box、Rc和Arc实现安全的堆内存共享

在Rust中,Box、Rc和Arc是实现堆内存管理与共享的关键智能指针类型,各自适用于不同的所有权场景。
Box:独占堆分配
Box用于将数据存储在堆上,提供栈上的指针引用。它适用于需要在编译时确定大小但实际数据较大的情况。

let heap_data = Box::new(42);
println!("值为: {}", heap_data); // 自动解引用
该代码将整数42分配到堆内存,Box拥有唯一所有权,超出作用域后自动释放。
Rc与Arc:多所有权共享
Rc(引用计数)允许多个只读共享所有权,适用于单线程环境;而Arc(原子引用计数)是其线程安全版本,可用于并发场景。
  • Rc::clone()增加引用计数,不进行深拷贝
  • Arc内部使用原子操作保障线程间安全共享

use std::sync::Arc;
use std::thread;

let data = Arc::new(vec![1, 2, 3]);
let data_clone = Arc::clone(&data);
thread::spawn(move || {
    println!("在线程中访问: {:?}", data_clone);
}).join().unwrap();
此例中,Arc确保多个线程安全共享同一数据,引用计数在线程结束时自动递减,最终释放堆内存。

4.2 RefCell与内部可变性:突破借用限制的安全途径

在Rust中,RefCell<T>提供了一种在运行时而非编译时强制执行借用规则的机制,实现了“内部可变性”模式。这允许我们在不可变引用存在的情况下修改数据内容,只要这种借用规则在运行时得到满足。
核心机制:动态借用检查
与Rc<T>结合使用时,RefCell<T>能实现多个所有者共享可变数据:

use std::rc::Rc;
use std::cell::RefCell;

let shared_data = Rc::new(RefCell::new(vec![1, 2, 3]));
let cloned = Rc::clone(&shared_data);

// 在运行时获取可变借用
cloned.borrow_mut().push(4);
println!("{:?}", shared_data.borrow()); // [1, 2, 3, 4]
上述代码中,borrow_mut()尝试获取可变引用,若已有活跃借用则 panic。该操作将借用检查推迟至运行时,为共享可变状态提供了安全路径。
适用场景与风险
  • 适用于无法在编译期确定借用关系的复杂数据结构
  • 常用于构建循环引用或缓存系统
  • 需警惕运行时 panic 风险,应确保逻辑上不会出现多重可变借用

4.3 避免循环引用:Weak指针的实际应用场景

在C++智能指针管理中,std::shared_ptr通过引用计数自动管理对象生命周期,但在双向关联场景下容易引发循环引用问题。此时,weak_ptr作为弱引用指针,不增加引用计数,成为打破循环的关键。
典型场景:父子节点关系
当父节点持有子节点的shared_ptr,而子节点又持有父节点的shared_ptr时,析构无法触发。解决方案是让子节点使用weak_ptr引用父节点。

#include <memory>
struct Parent;
struct Child {
    std::weak_ptr<Parent> parent; // 避免循环引用
};
struct Parent {
    std::shared_ptr<Child> child;
};
上述代码中,weak_ptr不会增加父对象的引用计数。访问时需调用lock()方法获取临时shared_ptr,确保对象仍存活。
资源缓存与观察者模式
weak_ptr也广泛用于缓存系统或事件监听器中,避免因强引用导致目标对象无法释放。

4.4 FFI调用中保持内存安全的边界防护策略

在跨语言调用中,FFI(外部函数接口)极易因内存管理差异引发安全问题。为确保 Rust 与 C 之间的数据交互安全,必须建立严格的边界防护机制。
所有权与生命周期控制
Rust 编译器无法管理 C 语言分配的内存,因此需显式标注内存归属。使用智能指针如 Box::into_raw 可移交所有权,但必须配对调用 Box::from_raw 防止泄漏。

#[no_mangle]
pub extern "C" fn create_buffer(size: usize) -> *mut u8 {
    let buffer = vec![0u8; size];
    Box::into_raw(buffer.into_boxed_slice()).as_mut_ptr()
}
该函数返回裸指针前已将 Vec 转为堆分配,调用方需保证后续通过配套释放接口回收资源。
输入验证与边界检查
所有来自外部的指针和长度参数必须进行非空、对齐及范围校验,避免越界访问。
  • 检查指针是否为 null 或未对齐
  • 验证缓冲区长度是否超出预设上限
  • 使用 std::slice::from_raw_parts 前确保内存合法可读

第五章:构建高可靠系统:Rust内存安全的工程价值

零成本抽象保障系统稳定性
Rust 的所有权与借用机制在编译期消除数据竞争,使得高并发服务无需依赖运行时垃圾回收。某金融支付平台迁移核心结算模块至 Rust 后,GC 停顿导致的超时错误下降 98%。
  • 所有权转移避免浅拷贝陷阱
  • 生命周期标注确保引用始终有效
  • 编译器强制检查防止悬垂指针
实战:异步任务中的内存安全设计
在 Tokio 运行时中管理跨线程共享状态时,传统语言易出现竞态条件。Rust 通过 Arc> 提供线程安全容器,且无额外性能损耗。
use std::sync::{Arc, Mutex};
use tokio::task;

let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];

for _ in 0..5 {
    let counter = Arc::clone(&counter);
    let handle = task::spawn(async move {
        let mut num = counter.lock().unwrap();
        *num += 1;
    });
    handles.push(handle);
}
// 所有任务自动等待完成,无需手动内存清理
for handle in handles {
    handle.await.unwrap();
}
跨团队协作中的可维护性提升
某云原生存储项目引入 Rust 后,新成员可通过编译错误快速理解资源管理规则。相比 C++ 模块平均 3.2 小时的代码审查时间,Rust 模块降至 1.1 小时。
指标C++模块Rust模块
内存泄漏事故/季度4.20
平均CR时间(小时)3.21.1
单元测试覆盖率76%91%
YOLOv8作物病害检测实战源码 这是一套基于YOLOv8n的农田病虫害目标检测系统,对叶片照片做目标检测,识别健康叶片、褐斑病、白粉病、锈病四类,并给出对应防治建议。全流程纯CPU可跑,配套交付完整Python源码、9章实战教程(md/html/pdf三种格式)、100张自造样本及YOLO标签、训练曲线与混淆矩阵截图、Tkinter界面和答辩PPT。 系统围绕五项功能展开:同一套推理逻辑覆盖图像、视频、摄像头三种来源;图形界面选文件即检测,画面叠彩色框标注病名与置信度,右侧面板同步给出症状与防治措施;检测记录自动写入CSV,统计页一键生成四类病害占比饼图;训练结束自动产出损失与精度曲线;内置防治建议文案库,检测命中即回填面板。 选型用YOLOv8n nano档,参数量约320万、权重约6.2MB,CPU单帧几十毫秒,小样本训练5到8分钟完成。数据由data_gen.py程序化绘制100张叶片图,固定随机种子,重跑分布一致,不依赖公开数据集。依赖全部锁版本,教程第7章整理了19条真实报错及排查方法,第8章给出换模型档、换PlantVillage数据集的迁移路径。 适合做计算机视觉方向课程设计或毕业设计的学生,也适合智慧农业方向想了解检测模型如何落进业务面板的学习者。不需要GPU,不需要系统学过目标检测,教程第3章会按需补齐原理。 使用时先pip install -r requirements.txt装好依赖,download_data.py下载预训练权重,data_gen.py生成样本后train.py训练,完成后用main.py infer批量检测或main.py gui启动界面。 立即下载

相关推荐

数据挖掘实战:决策树 + 聚类 + 关联规则,零 Key 离线可跑(Python 源码)

数据挖掘实战包。用 Python 标准库实现 CART 风格决策树、K-Means 聚类与 Apriori 关联规则,在虚构「星河便利店」会员表和购物篮上跑通分类、分群与购物篮分析,并给出准确率、轮廓系数、支持度/置信度/提升度。零第三方依赖、零 API Key 即可离线跑通。含 4 个样例、离线冒烟、中文 README(含「使用方法」)。均为作者原创可运行源码。MIT。作者 blog.youkuaiyun.com/mtl1994

产业园区运营负责人如何利用平台实现企业创新需求的精准分析与服务推送?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

科技中介服务机构在技术供需对接中如何实现服务流程的自动化与标准化?.docx

科技中介服务机构在技术供需对接中如何实现服务流程的自动化与标准化?

高校技术转移办公室人员在推动成果转化落地过程中,如何实现科技成果的高效推介与价值评估?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

产业园区如何高效对接企业技术需求与高校科研成果?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

国央企创新负责人如何快速掌握本地科技资源分布与匹配情况?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

科技中介服务机构如何通过数智工具提升技术需求挖掘的精准度?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

国央企创新负责人如何实现科技成果的精准识别与高效筛选?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

政府科技管理者如何在政策支持中更精准地识别和支持高价值科技项目?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

高校技术转移办公室人员如何系统化管理科技成果信息?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

科技中介服务机构如何构建标准化、模块化的智能服务工具?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

全桥LLC谐振变化器参数设计资料(闭环仿真+参数设计报告)

内容概要:本文档系统性地介绍了全桥LLC谐振变换器的闭环仿真建模与关键参数设计方法,涵盖其工作原理、谐振元件(如谐振电感、谐振电容、励磁电感)的计算与优化流程,并结合Simulink或Plecs等仿真平台构建闭环控制系统模型,重点验证变频控制策略下的软开关实现、系统增益特性、效率优化及动态响应性能。资料包含完整的仿真模型、参数设计报告、数学计算书及参考文献,支持从理论分析到工程实践的全流程研究,适用于高频高效DC-DC变换器的研发与教学应用。; 适合人群:电力电子、电气工程及其自动化等相关专业的高校学生、科研人员,以及从事开关电源、新能源变换器、工业电源研发的工程技术人员,具备电路拓扑基础与仿真软件操作能力者更佳。; 使用场景及目标:①深入掌握全桥LLC谐振变换器的工作机理与谐振参数设计准则;②学习并实现闭环反馈控制系统的建模与稳定性分析;③支撑科研课题、课程设计、毕业设计或实际产品开发中的拓扑选型与性能验证需求;④通过仿真与计算联动提升对软开关技术与效率优化的理解与应用能力。; 阅读建议:建议结合所提供的仿真文件与设计文档同步操作,按照“建模—参数计算—仿真验证—性能分析”的流程逐步推进,重点关注频率调节对ZVS/ZCS实现的影响,对比不同负载条件下的闭环响应差异,深化对谐振腔特性和控制策略协同作用的理解。

fab-pm-optimizer-python-entry-py39-20261021-v1-1-0

fab-pm-optimizer-python-entry-py39-20261021-v1-1-0

政府科技管理者如何提升区域科技成果转化项目的评价与筛选效率?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

PSIM-三相维也纳VIENNA整流器电压电流双闭环+中点电位平衡SVPWM控制仿真

内容概要:本文档详细介绍了一种基于PSIM软件实现的三相维也纳(VIENNA)整流器仿真模型,重点实现了电压电流双闭环控制与中点电位平衡的SVPWM调制策略。该仿真系统通过精确的控制算法有效提升了整流器的功率因数,降低了输入电流谐波含量,并解决了三电平拓扑中常见的直流侧中点电位偏移问题,具有较高的工程实用价值,适用于高效率、高功率密度的电力电子系统设计与科研验证。文档还整合了丰富的配套资源,涵盖多种电力电子变换器拓扑结构、先进控制算法及典型应用场景,形成了系统化的技术资料体系,有助于深入理解现代整流技术的核心原理与发展动态。; 适合人群:面向从事电力电子、电气工程、新能源变换系统等领域的科研人员、高校研究生以及具备一定仿真基础的工程技术人员。; 使用场景及目标:①深入研究三相VIENNA整流器的工作机理与控制特性;②掌握电压外环、电流内环双闭环控制结构的设计方法;③理解并实现SVPWM调制技术与中点电位平衡控制策略的协同作用;④开展相关控制算法的仿真验证、性能优化与实验对比,为高性能整流装置的研发提供理论支撑和技术原型。; 阅读建议:建议结合文中列出的其他仿真案例(如PWM整流器、LLC谐振变换器、DAB变换器等)进行横向对比学习,充分利用所提供的PSIM、MATLAB/Simulink等多平台仿真资源,重点关注控制逻辑与主电路的耦合关系,通过参数调试与波形分析深化对系统动态响应和稳态性能的理解,强化“理论—建模—仿真—优化”的闭环研究能力。

产业园区运营负责人如何利用数智工具提升园区企业的技术对接效率?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

jp-host-release.apk

jp-host-release.apk

ICD10 openGauss版

ICD10 openGauss版

上一篇: 单例、观察者、工厂模式全解析,JavaScript设计模式核心要点一网打尽
下一篇: Rust能做什么?这5个真实工业级项目颠覆你的认知
BytePerch
博客等级 码龄1年 164粉丝 1971原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值