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.vlaunch_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 ownershiptypes/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 的细节,下一篇再展开。

相关推荐
南雨北斗10 小时前
ThinkPHP6 设置响应 `Content-Type: application/json`
后端
用户39450717782410 小时前
Git 安装与 SSH 公钥配置教程
后端
政采云技术10 小时前
工单处理的智能革命:钉钉AI助理辅助系统探索
人工智能·后端·ai编程
Zane199411 小时前
钻石继承调用哪个方法?一文讲透 MRO 与 C3 线性化算法
后端·python
码事漫谈11 小时前
国产替代的硬核样本:金仓数据库如何撑起固井软件的数据底座
后端
老孙讲技术11 小时前
【4G IPC 上云】临时点位怎么免布线上云?listDeviceDetailsByPage + 辅码流预览|智慧工地实战
后端·物联网
铁皮饭盒12 小时前
DeepSeek V4 Pro 0813发布了, 也可以部署到 Codex 了
前端·javascript·后端
苏三说技术13 小时前
推荐一个牛逼的企业智能招聘系统
后端
达达尼昂13 小时前
Flutter AI Harness 如何让 Agent 参与软件开发全流程
android·人工智能·后端
k4m7v2pz13 小时前
Rust 长跑守护进程日志治理:切分、时区与结构化
开发语言·后端·rust·日志系统·日志轮转·ndjson