Carbon内存管理 #

一、内存管理概述 #

Carbon采用现代化的内存管理策略,结合手动管理和所有权系统,在保持性能的同时提高内存安全性。

二、指针 #

2.1 原始指针 #

carbon
var x: i32 = 42;
var p: i32* = &x;

Print("值: {0}", *p);  // 42
*p = 100;
Print("x = {0}", x);   // 100

2.2 空指针 #

carbon
var p: i32* = nullptr;

if (p != nullptr) {
  Print("{0}", *p);
} else {
  Print("空指针");
}

2.3 指针运算 #

carbon
var arr: [i32; 5] = (1, 2, 3, 4, 5);
var p: i32* = &arr[0];

Print("{0}", *p);       // 1
Print("{0}", *(p + 1)); // 2
Print("{0}", *(p + 2)); // 3

三、引用 #

3.1 引用基础 #

carbon
var x: i32 = 42;
var ref: i32& = x;

ref = 100;
Print("x = {0}", x);  // 100

3.2 引用与指针的区别 #

carbon
var x: i32 = 42;

// 引用:必须初始化,不能为空,不能重新绑定
var ref: i32& = x;

// 指针:可以为空,可以重新指向
var ptr: i32* = &x;
ptr = nullptr;

3.3 常量引用 #

carbon
fn PrintValue(ref: const i32&) {
  Print("{0}", ref);
  // ref = 100;  // 错误:不能修改常量引用
}

var x: i32 = 42;
PrintValue(x);

四、所有权系统 #

4.1 所有权概念 #

Carbon引入所有权系统来管理资源:

carbon
// 所有权转移
var s1: String = "Hello";
var s2: String = s1;  // s1的所有权转移给s2

// s1 不再有效
Print("{0}", s2);  // Hello
// Print("{0}", s1);  // 错误:s1已失效

4.2 借用 #

carbon
fn Length(s: String&) -> i32 {
  return s.Length();
}

var s: String = "Hello";
var len: i32 = Length(s);  // 借用s
Print("{0}", s);  // s仍然有效

4.3 可变借用 #

carbon
fn Append(s: String&, suffix: String) {
  s += suffix;
}

var s: String = "Hello";
Append(s, " World");
Print("{0}", s);  // Hello World

4.4 借用规则 #

carbon
fn Example() {
  var s: String = "Hello";
  
  // 规则1:可以有多个不可变借用
  var r1: String& = s;
  var r2: String& = s;  // OK
  
  // 规则2:只能有一个可变借用
  var m1: String& = s;
  // var m2: String& = s;  // 错误:已有可变借用
  
  // 规则3:不可变借用和可变借用不能同时存在
  // Print("{0}", r1);  // 错误:有可变借用时不能使用不可变借用
}

五、堆内存 #

5.1 动态分配 #

carbon
// 使用New分配堆内存
var p: i32* = New(i32);
*p = 42;
Delete(p);

// 数组分配
var arr: i32* = New(i32[10]);
for (i in 0..10) {
  arr[i] = i;
}
Delete(arr);

5.2 智能指针 #

carbon
// UniquePtr:独占所有权
var ptr: UniquePtr(i32) = MakeUnique(42);
Print("{0}", *ptr);

// SharedPtr:共享所有权
var shared: SharedPtr(i32) = MakeShared(42);
var shared2: SharedPtr(i32) = shared;
Print("{0}", *shared2);

5.3 自动释放 #

carbon
fn Example() {
  var ptr: UniquePtr(i32) = MakeUnique(42);
  // 使用ptr
  Print("{0}", *ptr);
  // 函数结束时自动释放
}

六、内存安全 #

6.1 空指针检查 #

carbon
fn SafeAccess(p: i32*) -> Optional(i32) {
  if (p == nullptr) {
    return None;
  }
  return Some(*p);
}

var p: i32* = nullptr;
match (SafeAccess(p)) {
  case Some(v) => Print("{0}", v);
  case None => Print("空指针");
}

6.2 边界检查 #

carbon
var arr: [i32; 5] = (1, 2, 3, 4, 5);

// 安全访问
match (arr.Get(10)) {
  case Some(v) => Print("{0}", v);
  case None => Print("越界");
}

6.3 悬垂引用防护 #

carbon
fn DanglingRef() -> i32& {
  var x: i32 = 42;
  return x;  // 编译错误:返回局部变量的引用
}

// 正确做法
fn SafeRef(x: i32&) -> i32& {
  return x;
}

七、RAII #

7.1 资源管理 #

carbon
class File {
  private var handle_: i32;
  
  fn New(path: String) -> File {
    return File(handle_ = OpenFile(path));
  }
  
  fn Delete(me&) {
    if (me.handle_ != -1) {
      CloseFile(me.handle_);
      me.handle_ = -1;
    }
  }
  
  fn Read(me, buffer: [u8]&. i32 size) -> i32 {
    return ReadFile(me.handle_, buffer, size);
  }
}

fn Example() {
  var file: File = File.New("data.txt");
  // 使用文件
  // 函数结束时自动关闭
}

7.2 作用域守卫 #

carbon
fn Example() {
  var resource: Resource = AcquireResource();
  defer {
    ReleaseResource(resource);
  }
  
  // 使用资源
  // 无论如何退出作用域,都会执行defer
}

八、内存布局 #

8.1 结构体布局 #

carbon
struct Point {
  var x: f64;  // 8字节
  var y: f64;  // 8字节
}

Print("Point大小: {0}", Point.Size);  // 16字节

8.2 内存对齐 #

carbon
struct Example {
  var a: u8;   // 1字节
  // 7字节填充
  var b: f64;  // 8字节
  var c: u8;   // 1字节
  // 7字节填充
}

Print("Example大小: {0}", Example.Size);  // 24字节

// 使用packed减少填充
packed struct PackedExample {
  var a: u8;   // 1字节
  var b: f64;  // 8字节
  var c: u8;   // 1字节
}

Print("PackedExample大小: {0}", PackedExample.Size);  // 10字节

8.3 查看布局 #

carbon
Print("偏移量 a: {0}", Example.OffsetOf("a"));  // 0
Print("偏移量 b: {0}", Example.OffsetOf("b"));  // 8
Print("偏移量 c: {0}", Example.OffsetOf("c"));  // 16

九、最佳实践 #

9.1 优先使用引用 #

carbon
// 好的做法:使用引用
fn Process(data: String&) {
  // ...
}

// 避免:使用指针(除非需要空值)
fn Process(data: String*) {
  if (data == nullptr) {
    return;
  }
  // ...
}

9.2 使用智能指针 #

carbon
// 好的做法:使用智能指针
var ptr: UniquePtr(Resource) = MakeUnique(Resource());

// 避免:手动管理
var ptr: Resource* = new Resource();
// ... 容易忘记 delete

9.3 避免内存泄漏 #

carbon
// 好的做法:使用RAII
{
  var file: File = File.New("data.txt");
  // 自动关闭
}

// 避免:手动管理
{
  var f: i32 = OpenFile("data.txt");
  // 可能忘记关闭
}

十、总结 #

本章我们学习了:

  1. 指针:原始指针、空指针、指针运算
  2. 引用:引用基础、常量引用
  3. 所有权系统:所有权转移、借用规则
  4. 堆内存:动态分配、智能指针
  5. 内存安全:空指针检查、边界检查
  6. RAII:资源管理、作用域守卫
  7. 内存布局:结构体布局、内存对齐

接下来让我们学习Carbon的高级特性!

最后更新:2026-03-27