V 编译器 v3 ownership 模式:编译与使用指南

V 编译器 v3 ownership 模式:编译与使用指南

上一篇文章梳理了 v3 的内存管理(scoped bump arena)。这一篇接着写 v3 的另一条主线:ownership checker------它怎么打开,怎么编译出来,怎么用。

一、为什么需要单独编译

v3 的标准二进制把 $if ownership ? 块全部编译裁掉了:

The standard v3 executable is built without -d ownership, so the ownership checker and its analysis stages are compiled out. It rejects both -ownership and -d ownership; the main V driver builds a separate ownership-enabled v3 executable only for an explicit v -ownership invocation.

所以 ./v3 -ownership foo.v 会直接报错:

csharp 复制代码
ownership support is not compiled into this v3 executable

正确做法是:先用主 v 编译出一个独立的 v3_ownership 二进制,再用它去编用户程序。

二、编译 v3_ownership

在仓库根目录执行:

sh 复制代码
./v -gc none -d ownership -o v3_ownership vlib/v3/v3.v

参数含义:

参数 作用
-gc none v3 拒绝任何 GC,必须显式
-d ownership 编译期 $define ownership,让 v3 源码里的所有 $if ownership ? 块全部编入
-o v3_ownership 产物文件名(任意)
vlib/v3/v3.v v3 编译器入口

这条命令正是 cmd/v/v.v 里 launch_v3_ownership_compiler() 调用的同一条:

v 复制代码
compilation_command := '${os.quoted_path(vexe)} -gc none -d ownership -o ${os.quoted_path(v3_exe)} ${os.quoted_path(v3_main_source)}'

如果走 v -ownership 驱动,它会自动把编译产物缓存到 $VTMP/v/delegated_v3/<vroot-hash>/v3_ownership,无需手动管理。

产物对比

二进制 大小 说明
v ~6.3 MB 主 v 驱动
v2 / v3 ~5.9 MB 标准 v3(不含 ownership)
v3_ownership ~9.1 MB 带 ownership checker 的 v3

因为 -d ownership 把 types/scope.v 的 scope 路径、types/checker_parallel.v 的 fork 处理、ownership drop 等大块代码都拉进来了,所以 v3_ownership 比标准 v3 大 50%+。

三、v3_ownership 怎么用

虽然叫 v3_ownership,但内部命令名仍是 v3,CLI 跟 v 几乎一样:

sh 复制代码
./v3_ownership [run|test] <file.v|directory> [options]

关键:必须加 -ownership 才会真正启用 ownership 检查。不加就和普通 v3 没区别(checker 已经在二进制里了,但运行时开关没打开)。

基本用法

sh 复制代码
# 编译一个程序(带 ownership 检查)
./v3_ownership -ownership -o my_prog my_prog.v

# 编译并直接跑
./v3_ownership -ownership run my_prog.v

# 跑测试
./v3_ownership -ownership test my_pkg/

# 只生成 C,不链接(看 codegen)
./v3_ownership -ownership -o my_prog.c my_prog.v

通用选项

| 选项 | 说明 |
|------------------------------|----------------|------|----------|----|
| -o <output> | 输出二进制或 .c 文件 |
| `-b <c | arm64 | wasm | eval>` | 后端 |
| -os <name> -arch <name> | 交叉编译目标 |
| -cc <compiler> | C 编译器 |
| -prod -c99 -shared -strict | C 构建模式 |
| -v | 详细阶段计时 |
| -no-memory-limit | 关闭 10 GiB 内存保护 |
| -d <name> | 编译期 define |

四、几个容易踩的坑

1. -ownership ≠ -d ownership

  • 编译期 -d ownership :让 v3 自己的 $if ownership ? 块参与编译。这是构建 v3_ownership 那一步要传的参数。
  • 运行时 -ownership :决定这一次编译 是否走 ownership checker,且只在 v3_ownership 这类二进制上才有意义。
  • v3.v 里的注释特意强调运行时 -ownership 不能把 ownership 暴露给目标程序的 $if 或 _d_ownership.v 文件------它只加载 builtin overlays。

vlib/v3/tests/drop_codegen_test.v 里的写法(编目标程序时)就是 -d ownership 裸 define 形式:

v 复制代码
compile := os.execute('${v3_bin} ${src} -d ownership -b c -o ${out}')

跟 -ownership 一样能激活 checker,只是作用层次不同。

2. -ownership 只支持直接编译

cmd/v/v.v 里的 is_ownership_relevant_command() 会拒绝 run / crun:

go 复制代码
v: `-ownership` currently supports direct compilation only. Use `v -ownership module_dir`.

如果你想编译完直接跑,得用 ./v3_ownership -ownership run ...(绕过 v 驱动),或者拆成两步。

3. 复杂模块可能触发 codegen bug

我拿 net.http 那个 ip_check.v 试了一下,v3_ownership 编它的时候会在两处 drop 点崩:

rust 复制代码
src.c:31616:21: error: member reference base type 'int' is not a structure or union
                t->cur_size -= (0).size;

这是 ownership pass 在「作用域退出时释放数组」的路径上,把 struct 当成 literal 0 在引用。标准 v3 不会触发,v3_ownership 会------看起来是当前 ownership checker 的一个边界 bug(与 VMemoryBlock / scope drop 相关),不是二进制本身的问题。最小复现一般能稳定出现,建议提 issue。

五、一个跑通的最小例子

/tmp/v3own_demo/main.v:

v 复制代码
module main

struct Box {
mut:
	value int
}

fn make_box(v int) &Box {
	return &Box{value: v}
}

fn main() {
	b := make_box(42)
	println('box: ${b.value}')
}
sh 复制代码
$ ./v3_ownership -ownership -o /tmp/v3own_demo/box /tmp/v3own_demo/main.v
$ /tmp/v3own_demo/box
box: 42

ownership pass 跑完生成的 C 代码,在 &Box{...} 离开 make_box 时按 checker 规则正确释放,没有 leak。

六、总结

步骤 命令
1. 编译 v3_ownership(一次性) ./v -gc none -d ownership -o v3_ownership vlib/v3/v3.v
2. 用它编你的模块 ./v3_ownership -ownership -o my_prog my_prog.v
3. (或)走 v 驱动自动维护 v -ownership my_prog_dir/

核心点就两个:

  1. 标准 v3 不带 ownership checker ------必须先用 ./v -gc none -d ownership -o v3_ownership vlib/v3/v3.v 编出专用二进制。
  2. 运行时开关 -ownership 必须显式传------否则二进制就当普通 v3 用。

至于 ownership checker 自己的规则、move semantics、borrow check 的细节,下一篇再展开。

相关推荐
独泪了无痕3 小时前
Spring Data Redis 快速上手
spring boot·redis·后端
m0_639906946 小时前
Linux 操作系统入门:目录结构、服务排查常用命令、Shell 脚本基础
linux·运维·后端
holly就是我7 小时前
AI 编程助手为什么跑偏?用开源 ccglass 看清 Prompt、工具调用和 Token 消耗
人工智能·后端
鸿蒙开发7 小时前
共享 Schema 与 SchemaFactory
前端·后端·harmonyos
用户788477316347 小时前
小程序后端三选一:云开发、.NET WebAPI、Node,我按客户现状分了三种答案
后端
aiopencode7 小时前
局域网设备抓包怎么做?用 TraceEagle 抓电视、游戏机和 IoT 流量
后端·ios
智驭未来掌门人7 小时前
CLion 开发 Qt 项目的优势
后端
Zwawa7 小时前
编译器工具链:GCC、Clang、MSVC、ICC、armclang
c语言·嵌入式·编译器
EnCi Zheng8 小时前
后端怎么把AI接口稳定安全低成本接进业务:超时重试、密钥隔离与成本熔断清单
人工智能·后端·安全·架构·api
Bazingga8 小时前
从一家酒店讲懂Docker
后端