Rust 数组与指针(二)

这一节,我们继续探索数组与指针。

内存回收

在开始之前,你一定要清醒,“栈” 内存是系统自动分配自动回收的,“堆” 内存需要你自己申请自己并回收。我们这里所讲的 “内存回收” 是指 “堆” 内存。Rust 的变量默认会放到 “栈” 上,除非你主动去干涉。

在上节的最后,我们实现了一个叫做 MyArray<T> 的动态增长数组,还给 MyArray<T> 实现了一个叫做 Droptrait。我们给一个类型实现 Drop 后,当值离开作用域时,就会自动地调用 drop 方法。我们也可以将 drop 叫做析构函数。标准库 给出了一个例子:

继续阅读

Rust 数组与指针(一)

这一节主要介绍 Rust 中数组与指针的相关概念。希望通过本文,你对 Rust 有更深入的了解。

什么是数组?

数组是一组包含相同数据类型 T 的集合,存储在连续的内存区域中。理论上,内存(我们暂且不去讨论物理内存与虚拟内存)相当于一个类型为 u8、长度为 usize 的数组,内存操作相当于操作这个数组。因此,usize 可以表示每个内存地址。Rust 又规定,isize 的最大值是对象和数组大小的理论上限,这样可以确保 isize 可用于计算指向对象和数组的指针之间的差异,并可寻址对象中的每个字节及末尾的一个字节。

数组使用 [] 来创建,其大小在编译期间就已经确定,数组的类型被标记为 [T; size],表示一个类型为 Tsize个元组的数组。数组的大小是固定的,但其中的元素是可以被更改的。

继续阅读

golang time

在我们编程过程中,经常会用到与时间相关的各种务需求,下面来介绍 golang 中有关时间的一些基本用法,我们从 time 的几种 type 来开始介绍。

时间可分为时间点与时间段,golang 也不例外,提供了以下两种基础类型:

  • 时间点(Time)
  • 时间段(Duration)

除此之外 golang 也提供了以下类型,做一些特定的业务:

  • 时区(Location)
  • Ticker
  • Timer(定时器)

我们将按以上顺序来介绍 time 包的使用。

继续阅读

在树莓派上玩转 Rust :交叉编译

本文面向于对 Rust 和 Linux 有一定基础的读者。

在开始之前,请先确保你已经拥有了一个树莓派,和一台装有 Linux 的物理机或者虚拟机,装好 Rust,并且已经为树莓派刷好了系统(推荐官方系统),能够在你电脑上用 ssh 连接至树莓派。期间你可能会遇到问题,请尝试从文末给出的连接找到答案。

通常,要得到可在树莓派上运行的二进制文件有两种方式。一种是在树莓派上安装 Rust,编译源码并运行。由于树莓派硬件资源的限制,在树莓派上编译 Rust 极其缓慢,尤其是在 zero w 这类型号上,并且编写源码也是件麻烦的事。另一种是在你的电脑上编写源码,交叉编译,并通过 scp 命令发送至树莓派。在开发时,你也可以利用 rsync 工具,将编译好的二进制文件同步至树莓派。

继续阅读

交叉编译和静态链接 Rust 库

Photo by Zun Zun from Pexels

在 CSIS 中,我们过去使用 Python 编写后端,同时为 Incident Response Toolkit 编写一些 C/C++ 代码。

几年前,主要是由于性能原因,我们开始用 Rust 替换 Python 重写了一些特定的后端服务,并取得了巨大的成功。现在,为了便于开发和测试,我们正在探索将 C/C++ 代码库的某些部分也迁移到 Rust 的方法。

为了做到这一点,我们决定尝试将Rust集成到现有的代码库中,而不是一次重写所有内容。

下面是我们实验的摘要,以及编写一个Rust库并从 C/C++ 应用程序调用它的框架。

继续阅读

微软:为啥安全的系统得用 Rust 写

图片来自 Microsoft Security Response Center

本系列文章中,我们探讨了主动采取一些措施消除一类漏洞的必要性,并介绍了在 Microsoft 的代码中发现的一些内存安全问题的例子,这些问题可以用其他语言避免。现在我们来看看为什么我们认为 Rust 是目前可用的 C 和 C++ 最好的替代品。

虽然,已经有许多非常好用的内存安全语言,广泛应用于微软内外,包括 .NET 语言(如 C# 和 F#)和其他语言(如 Swift, Go, and Python)。 我们鼓励正在使用 C 或 C++ 的人考虑使用这些语言中的一种。然而,我们正在讨论对安全的系统编程语言的需求(即,可以构建其他软件运行的系统的语言,如OS内核)。此类工作负载需要 C,C ++ 和 Rust 提供的速度和可预测的性能。通过垃圾回收实现内存安全的语言不是系统编程的理想选择,因为它们的运行时会导致不可预测的性能和不必要的开销。

性能和控制

在考虑为什么Rust是一个很好的替代方案时,最好考虑一下我们不能因为从 C 或 C++ 转换而放弃什么——即性能和控制。 Rust,就像 C 和 C++ 一样,有一个最小的和可选的“运行时”。Rust 的标准库依赖于 libc 来支持它的平台,就像 C 和 C++ 那样,但是标准库也是可选的,所以在没有操作系统的平台上也是可以运行的。

Rust 与 C 和 C++ 一样,也为程序员提供了对何时分配内存以及分配多少内存的细粒度控制,从而使程序员能够非常清楚地了解程序运行时将如何执行。这对于原始性能,控制和可预测性的性能意味着什么,Rust,C 和 C ++可以用类似的术语来思考。

继续阅读

在 Rust 中不能做什么

Photo by Elle Hughes from Pexels

编者注:上周 Armin 在自己的博客上首次发布了这个版本。如果你想再次阅读这篇文章,或者想看看 Armin 还在做什么,一定要去看看。

去年一直很有趣,因为我们用 Rust 建造了很多好东西,并且这是第一次在开发体验上没有更大的障碍。虽然过去的一年我们一直使用 Rust,但是现在感觉不同了,因为生态系统更加稳定,我们遇到的语言或者工具的问题也越来越少。

也就是说,与那些不熟悉 Rust 的人交谈——甚至与同事集体讨论 API——很难摆脱Rust可以成为令人心旷神怡的冒险的感觉。这就是为什么拥有无压力体验的最佳方式是,提前了解你不能(或不应该尝试)做的事情。 知道某些事情无法完成有助于让你的思想回到正确的轨道上。

所以根据我们的经验,这里有一些在 Rust 中不能做的事情,以及应该做什么,我认为应该更好地了解。

继续阅读

从 Rust 库中公开 FFI

Photo by Dominika Roseclay from Pexels

Wikipedia 将 FFI 定义为一种机制,通过这种机制,用一种编程语言编写的程序可以调用或使用用另一种编程语言编写的服务。

FFI 可用于加快程序执行(这在 Python 或 Ruby 这类动态语言中很常见),或者只是因为你想使用一些其他语言编写的库(例如 TensorFlow 的核心库是用 C++ 写的,并暴露了 C API,允许其他语言使用)。

为 Rust 库编写 FFI 并不难,但是却有一些挑战和可怕的部分,主要是你要使用指针和 unsafe1。这可能会脱离 Rust 的内存安全模型,换句话说,编译器无法检查一切是否正常,因此内存管理和安全保障取决于开发人员。

在这篇文章中,我将讲述我对 Rust 和 FFI 的经验,基于 battery-ffi ,它将 FFI 暴露给我的另一个 crate — battery。我想做的是提供一个 C 接口来创建特定于 Rust 的结构,并能够从它们获取数据。

继续阅读

Rust 零成本的抽象

图片来自 pexels.com

零成本抽象的概念对于某些编程语言非常重要,比如 Rust 和 C++,这些语言的目的是使用户能够用相对较少的努力编写具有出色性能的程序。因为这个概念是 Rust 设计和我的工作的基础,所以我想研究一下,零成本抽象到底是什么。

C++ 的最初开发者Bjarne Stroustrup在其原文中总结了这个想法:

你不用的东西,就不用付钱。而且: 你所使用的代码是最好的。

在这个定义中,有两个因素使某些东西成为一个适当的零成本抽象:

  • 没有全局开销: 零成本抽象不应该对不使用它的程序的性能产生负面影响。例如,它不能要求每个程序都带有一个沉重的语言运行时,以使唯一使用该特性的程序受益。
  • 最优性能: 一个零成本的抽象应该被编译成最佳的解决方案实现,而这个解决方案是有人用较低级别的原语编写的。它不能引入没有抽象就可以避免的额外成本。

然而,我认为重要的是要记住,第三个要求是什么东西是零成本抽象。它经常被忽视,因为它只是所有好的抽象的一个要求,无论是否为零:

  • 改进用户体验: 抽象的要点是提供一个新工具,它由较低级别的组件组装而成,使用户能够更容易地编写他们想要编写的程序。与所有抽象一样,零成本抽象实际上必须提供比其他抽象更好的体验。
继续阅读