第5.3章: 解引用

English

概述

指针存储一个地址。解引用意味着: 用该指针访问位于那个地址上的对象。

在本章中,你将学到:

1. 解引用是什么意思?

如果指针存储了一个地址,那么解引用就是“走到那个地址, 访问存储在那里的对象”。


value:
Address: 3000
Memory: [ 42 ]

p:
Address: 4000
Memory: [ 3000 ]   ← p stores address of value

#include <memory>

int value{42};
int *p = ::std::addressof(value);

int x = *p;   // x becomes 42

2. 通过指针读取

解引用让你能读取指针地址处存储的值。


int n{100};
int *p = ::std::addressof(n);

int copy = *p;   // copy becomes 100

3. 通过指针写入

解引用同样让你能修改指针所指的对象。


int n{5};
int *p = ::std::addressof(n);

*p = 20;   // changes n to 20

4. 解引用指向指针的指针

如果你有指向指针的指针,可以解引用两次。


int value{7};
int *p = ::std::addressof(value);
int **pp = ::std::addressof(p);

int x = **pp;   // x becomes 7

value:
Address: 3000
Memory: [ 7 ]

p:
Address: 4000
Memory: [ 3000 ]

pp:
Address: 5000
Memory: [ 4000 ]

**pp → *p → value → 7

5. 解引用 nullptr 是未定义行为

在解引用之前,指针必须指向一个有效对象。 解引用 nullptr 是未定义行为。


int *p = nullptr;

// *p = 10;   // undefined behavior — never do this

6. 解引用无效指针是严重的内存安全漏洞

解引用无效指针不只是 bug —— 它是一个 严重的内存安全漏洞。它可能导致:

一个指针在以下情况是无效的:

示例


// 1. Null pointer
int *p = nullptr;
// *p = 10;   // undefined behavior

// 2. Uninitialized pointer
int *q;
// *q = 10;   // undefined behavior

// 3. Dangling pointer
int *r = nullptr;
{
    int x{5};
    r = ::std::addressof(x);
} // x is destroyed here
// *r = 10;   // undefined behavior

// 4. Forged pointer
int *s = reinterpret_cast(12345);
// *s = 10;   // undefined behavior

规则: 只有当你绝对确定某个指针指向一个有效、存活的对象时,才解引用它。

7. 使用 sanitizer 检测无效解引用

现代编译器提供了在运行时检测无效指针解引用的工具。 开发期间你应当始终启用它们。

AddressSanitizer


-fsanitize=address

可检测:

内存标记(WebAssembly)


-fsanitize=memtag

可检测:

这些工具让指针缺陷更容易被发现和修复。

8. 打印解引用得到的值

解引用得到的值可以像其他任何值一样打印。


#include <fast_io.h>
#include <memory>

int n{55};
int *p = ::std::addressof(n);

println(*p);   // prints 55

要点