@ohos-graphics/stability-code-review 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +169 -0
- package/SKILL.md +518 -0
- package/bin/install.js +165 -0
- package/config/rules.yaml +445 -0
- package/config/whitelist.yaml +52 -0
- package/package.json +40 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_001.md +275 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_002.md +273 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_003.md +305 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_004.md +350 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_005.md +301 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_006.md +320 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_007.md +432 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_008.md +394 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_009.md +425 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_010.md +472 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_011.md +204 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_012.md +210 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_013.md +226 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_014.md +222 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_015.md +256 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_016.md +269 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_017.md +222 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_018.md +336 -0
- package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_001.md +414 -0
- package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_002.md +335 -0
- package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_003.md +284 -0
- package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_004.md +313 -0
- package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_005.md +364 -0
- package/references/ExceptionHandling/StabilityCodeReview_ExceptionHandling_001.md +142 -0
- package/references/ExceptionHandling/StabilityCodeReview_ExceptionHandling_002.md +222 -0
- package/references/ExceptionHandling/StabilityCodeReview_ExceptionHandling_003.md +383 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_001.md +258 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_002.md +131 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_003.md +220 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_004.md +224 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_005.md +250 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_006.md +153 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_007.md +169 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_008.md +153 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_009.md +144 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_010.md +152 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_011.md +221 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_012.md +318 -0
- package/references/InitializationOrder/StabilityCodeReview_InitializationOrder_001.md +411 -0
- package/references/Lifecycle/StabilityCodeReview_Lifecycle_001.md +255 -0
- package/references/Lifecycle/StabilityCodeReview_Lifecycle_002.md +177 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_001.md +332 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_002.md +261 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_003.md +428 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_004.md +400 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_005.md +364 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_006.md +359 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_007.md +279 -0
- package/references/PROBLEM_TEMPLATE.md +65 -0
- package/references/PerformanceStability/StabilityCodeReview_PerformanceStability_001.md +380 -0
- package/references/PerformanceStability/StabilityCodeReview_PerformanceStability_002.md +437 -0
- package/references/REPORT_TEMPLATE.csv +5 -0
- package/references/REPORT_TEMPLATE.md +132 -0
- package/references/RULE_DEVELOPMENT_GUIDE.md +711 -0
- package/references/RULE_INDEX.md +101 -0
- package/references/RULE_TEMPLATE.md +192 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_001.md +334 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_002.md +425 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_003.md +420 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_004.md +409 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_005.md +445 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_006.md +384 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_007.md +395 -0
- package/scripts/add-rule.py +423 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule_id: "StabilityCodeReview_ResourceManagement_007"
|
|
3
|
+
name: "智能指针与裸指针混用"
|
|
4
|
+
category: "资源管理"
|
|
5
|
+
severity: "CRITICAL"
|
|
6
|
+
language: ["cpp", "c++"]
|
|
7
|
+
author: "OH-Department7 Stability Team"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# 智能指针与裸指针混用
|
|
11
|
+
|
|
12
|
+
## 问题描述
|
|
13
|
+
|
|
14
|
+
C++标准库智能指针(unique_ptr、shared_ptr)、OpenHarmony sptr、裸指针(raw pointer)任意两两不能混用。混用会导致所有权不清晰,引发双重释放、内存泄漏、use after free等严重问题。
|
|
15
|
+
|
|
16
|
+
## 检测示例
|
|
17
|
+
|
|
18
|
+
### ❌ 问题代码
|
|
19
|
+
|
|
20
|
+
```cpp
|
|
21
|
+
// 场景1:unique_ptr::release后delete
|
|
22
|
+
void bad_unique_release() {
|
|
23
|
+
std::unique_ptr<Foo> uptr(new Foo());
|
|
24
|
+
Foo* raw = uptr.release(); // 转移所有权到裸指针
|
|
25
|
+
// ... 使用raw
|
|
26
|
+
delete raw; // 危险:裸指针管理,容易出错
|
|
27
|
+
// 如果后续代码继续使用uptr,会崩溃
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 场景2:对shared_ptr::get返回的指针delete
|
|
31
|
+
void bad_shared_get_delete() {
|
|
32
|
+
std::shared_ptr<Foo> sptr = std::make_shared<Foo>();
|
|
33
|
+
Foo* raw = sptr.get();
|
|
34
|
+
delete raw; // 严重错误:double free!
|
|
35
|
+
// shared_ptr析构时会再次delete
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 场景3:裸指针构造多个智能指针
|
|
39
|
+
void bad_raw_multi_owner() {
|
|
40
|
+
Foo* raw = new Foo();
|
|
41
|
+
std::unique_ptr<Foo> uptr(raw);
|
|
42
|
+
std::shared_ptr<Foo> sptr(raw); // 严重错误:double free!
|
|
43
|
+
// 两个智能指针都认为自己拥有所有权
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 场景4:shared_ptr和sptr混用
|
|
47
|
+
void bad_sptr_shared() {
|
|
48
|
+
Foo* raw = new Foo();
|
|
49
|
+
sptr<Foo> oh_sptr(raw);
|
|
50
|
+
std::shared_ptr<Foo> std_sptr(raw); // 严重错误:double free!
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 场景5:unique_ptr reset裸指针
|
|
54
|
+
void bad_unique_reset() {
|
|
55
|
+
Foo* raw = new Foo();
|
|
56
|
+
std::unique_ptr<Foo> uptr;
|
|
57
|
+
// ... 一些代码
|
|
58
|
+
uptr.reset(raw); // 危险:raw的所有权转移,但可能被其他地方释放
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 场景6:sptr和裸指针混用
|
|
62
|
+
void bad_sptr_raw() {
|
|
63
|
+
Foo* raw = new Foo();
|
|
64
|
+
sptr<Foo> ptr(raw);
|
|
65
|
+
// ... 一些代码
|
|
66
|
+
delete raw; // 严重错误:sptr已经管理,double free!
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 场景7:从unique_ptr获取裸指针后构造shared_ptr
|
|
70
|
+
void bad_unique_to_shared() {
|
|
71
|
+
std::unique_ptr<Foo> uptr(new Foo());
|
|
72
|
+
Foo* raw = uptr.get();
|
|
73
|
+
std::shared_ptr<Foo> sptr(raw); // 错误:所有权混乱
|
|
74
|
+
// uptr和sptr都认为自己拥有所有权
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// 场景8:get()返回的指针用于构造另一个智能指针
|
|
78
|
+
void bad_get_construct() {
|
|
79
|
+
std::shared_ptr<Foo> sptr1 = std::make_shared<Foo>();
|
|
80
|
+
std::shared_ptr<Foo> sptr2(sptr1.get()); // 错误:两个独立的引用计数
|
|
81
|
+
// sptr1和sptr2都会尝试delete同一个对象
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### ✅ 修复方案
|
|
86
|
+
|
|
87
|
+
```cpp
|
|
88
|
+
// 修复场景1:保持unique_ptr管理
|
|
89
|
+
void good_unique() {
|
|
90
|
+
std::unique_ptr<Foo> uptr = std::make_unique<Foo>();
|
|
91
|
+
uptr->DoSomething();
|
|
92
|
+
// unique_ptr自动释放,不需要手动delete
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// 修复场景2:shared_ptr自动管理
|
|
96
|
+
void good_shared() {
|
|
97
|
+
std::shared_ptr<Foo> sptr = std::make_shared<Foo>();
|
|
98
|
+
Foo* raw = sptr.get(); // 仅用于观察,不拥有所有权
|
|
99
|
+
raw->DoSomething(); // 可以使用,但不要delete
|
|
100
|
+
// shared_ptr自动释放
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// 修复场景3:使用make_unique/make_shared
|
|
104
|
+
void good_make() {
|
|
105
|
+
auto uptr = std::make_unique<Foo>(); // 推荐
|
|
106
|
+
auto sptr = std::make_shared<Foo>(); // 推荐
|
|
107
|
+
// 每个资源只有一个所有者
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 修复场景4:转移所有权用std::move
|
|
111
|
+
void good_ownership_transfer() {
|
|
112
|
+
std::unique_ptr<Foo> uptr1 = std::make_unique<Foo>();
|
|
113
|
+
std::unique_ptr<Foo> uptr2 = std::move(uptr1); // 正确:转移所有权
|
|
114
|
+
// uptr1变为nullptr,uptr2拥有所有权
|
|
115
|
+
|
|
116
|
+
std::shared_ptr<Foo> sptr1 = std::make_shared<Foo>();
|
|
117
|
+
std::shared_ptr<Foo> sptr2 = sptr1; // 正确:共享所有权,引用计数+1
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 修复场景5:使用shared_from_this
|
|
121
|
+
class Foo : public std::enable_shared_from_this<Foo> {
|
|
122
|
+
public:
|
|
123
|
+
std::shared_ptr<Foo> getShared() {
|
|
124
|
+
return shared_from_this(); // 正确:获取shared_ptr
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// 修复场景6:sptr正确使用
|
|
129
|
+
void good_sptr() {
|
|
130
|
+
sptr<Foo> ptr = new Foo(); // sptr管理
|
|
131
|
+
ptr->DoSomething();
|
|
132
|
+
// sptr自动释放
|
|
133
|
+
// 不要手动delete,不要用裸指针构造其他智能指针
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// 修复场景7:明确所有权边界
|
|
137
|
+
void process_foo(Foo* raw) {
|
|
138
|
+
// 函数签名表明:不获取所有权,仅观察
|
|
139
|
+
raw->DoSomething();
|
|
140
|
+
// 不delete
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
std::unique_ptr<Foo> create_foo() {
|
|
144
|
+
// 函数签名表明:返回所有权
|
|
145
|
+
return std::make_unique<Foo>();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// 修复场景8:使用weak_ptr打破循环引用
|
|
149
|
+
class Bar {
|
|
150
|
+
public:
|
|
151
|
+
std::weak_ptr<Bar> partner; // 使用weak_ptr避免循环引用
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
void good_weak_ptr() {
|
|
155
|
+
auto bar1 = std::make_shared<Bar>();
|
|
156
|
+
auto bar2 = std::make_shared<Bar>();
|
|
157
|
+
bar1->partner = bar2; // weak_ptr不增加引用计数
|
|
158
|
+
bar2->partner = bar1;
|
|
159
|
+
// 没有循环引用,正常释放
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// 修复场景9:unique_ptr转shared_ptr
|
|
163
|
+
void good_unique_to_shared() {
|
|
164
|
+
std::unique_ptr<Foo> uptr = std::make_unique<Foo>();
|
|
165
|
+
std::shared_ptr<Foo> sptr = std::move(uptr); // 正确:转移所有权
|
|
166
|
+
// uptr变为nullptr,sptr拥有所有权
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// 修复场景10:统一使用一种智能指针类型
|
|
170
|
+
class ResourceManager {
|
|
171
|
+
public:
|
|
172
|
+
// 推荐:统一使用shared_ptr
|
|
173
|
+
using Ptr = std::shared_ptr<Resource>;
|
|
174
|
+
|
|
175
|
+
Ptr create() {
|
|
176
|
+
return std::make_shared<Resource>();
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
void use(Ptr p) {
|
|
180
|
+
p->DoSomething();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// 或者统一使用unique_ptr(性能更好)
|
|
184
|
+
using UniquePtr = std::unique_ptr<Resource>;
|
|
185
|
+
|
|
186
|
+
UniquePtr createUnique() {
|
|
187
|
+
return std::make_unique<Resource>();
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## 检测范围
|
|
193
|
+
|
|
194
|
+
检查以下混用模式:
|
|
195
|
+
|
|
196
|
+
- `unique_ptr::release()` 后对裸指针操作
|
|
197
|
+
- `shared_ptr::get()` 返回的指针被delete
|
|
198
|
+
- 同一裸指针构造多个智能指针
|
|
199
|
+
- `unique_ptr` 和 `shared_ptr` 相互转换不当
|
|
200
|
+
- `sptr` 和 `std::shared_ptr` 混用
|
|
201
|
+
- `reset()` 使用裸指针参数
|
|
202
|
+
- `get()` 返回值用于构造新智能指针
|
|
203
|
+
|
|
204
|
+
## 检测要点
|
|
205
|
+
|
|
206
|
+
1. 识别智能指针变量声明
|
|
207
|
+
2. 追踪裸指针变量来源
|
|
208
|
+
3. 检测`release()`、`get()`的返回值使用
|
|
209
|
+
4. 检测裸指针被多个智能指针管理
|
|
210
|
+
5. 检测对`get()`返回值调用`delete`
|
|
211
|
+
|
|
212
|
+
## 风险流分析(RiskFlow)
|
|
213
|
+
|
|
214
|
+
- **RISK_SOURCE**:智能指针和裸指针混用
|
|
215
|
+
- **RISK_TYPE**:资源管理混乱
|
|
216
|
+
- **RISK_PATH**:智能指针管理 <-> 裸指针管理 -> 所有权冲突
|
|
217
|
+
- **IMPACT_POINT**:双重释放、内存泄漏、程序崩溃
|
|
218
|
+
|
|
219
|
+
## 影响分析(ImpactAnalysis)
|
|
220
|
+
|
|
221
|
+
- **Trigger**:同一资源被多个指针"拥有"
|
|
222
|
+
- **Propagation**:所有权不清晰导致重复释放或泄漏
|
|
223
|
+
- **Consequence**:double free、use after free、内存泄漏
|
|
224
|
+
- **Mitigation**:统一使用一种智能指针类型,明确所有权
|
|
225
|
+
|
|
226
|
+
## 误报排除
|
|
227
|
+
|
|
228
|
+
| 场景 | 识别特征 | 处理方式 |
|
|
229
|
+
|------|----------|----------|
|
|
230
|
+
| std::move转移所有权 | std::move(ptr) | 不报 |
|
|
231
|
+
| shared_from_this | shared_from_this() | 不报 |
|
|
232
|
+
| make_shared/make_unique | make_XXX() | 不报 |
|
|
233
|
+
| weak_ptr | weak_ptr<T> | 不报 |
|
|
234
|
+
| NOPROTECT标记 | 有 // NOPROTECT 注释 | 不报 |
|
|
235
|
+
| 第三方库 | 位于 third_party 目录 | 白名单排除 |
|
|
236
|
+
|
|
237
|
+
### release()的正确使用场景区分
|
|
238
|
+
|
|
239
|
+
`release()`是所有权转移的正确方式,不应误报为"混用":
|
|
240
|
+
|
|
241
|
+
#### ✅ 安全场景(release()用于所有权转移)
|
|
242
|
+
|
|
243
|
+
```cpp
|
|
244
|
+
// 安全场景1:unique_ptr::release()转移所有权给裸指针,然后正确管理
|
|
245
|
+
std::unique_ptr<Data> uptr = std::make_unique<Data>();
|
|
246
|
+
Data* raw = uptr.release(); // uptr放弃所有权,raw接管
|
|
247
|
+
// raw现在拥有唯一所有权,可以安全管理
|
|
248
|
+
delete raw; // 安全:raw是唯一所有者
|
|
249
|
+
|
|
250
|
+
// 安全场景2:release()后交给C API管理
|
|
251
|
+
std::unique_ptr<Buffer> buffer = CreateBuffer();
|
|
252
|
+
C_API_Handle* handle = C_API_Create(buffer.release()); // 转移给C API
|
|
253
|
+
// C API负责释放,不再需要手动delete
|
|
254
|
+
|
|
255
|
+
// 安全场景3:release()返回所有权给调用者
|
|
256
|
+
std::unique_ptr<Resource> CreateResource() {
|
|
257
|
+
auto uptr = std::make_unique<Resource>();
|
|
258
|
+
// 初始化资源
|
|
259
|
+
return uptr; // 或 return uptr.release(); 返回裸指针让调用者选择管理方式
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// 安全场景4:release()配合外部管理器
|
|
263
|
+
std::unique_ptr<Node> node = std::make_unique<Node>();
|
|
264
|
+
Node* rawPtr = node.release();
|
|
265
|
+
externalManager.Register(rawPtr); // 外部管理器接管所有权
|
|
266
|
+
// externalManager负责释放
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
#### ❌ 危险场景(release()后所有权混乱)
|
|
270
|
+
|
|
271
|
+
```cpp
|
|
272
|
+
// 危险场景1:release()后裸指针被多个智能指针管理
|
|
273
|
+
std::unique_ptr<Data> uptr = std::make_unique<Data>();
|
|
274
|
+
Data* raw = uptr.release();
|
|
275
|
+
std::shared_ptr<Data> sptr1(raw); // ❌ sptr1管理raw
|
|
276
|
+
std::shared_ptr<Data> sptr2(raw); // ❌ sptr2也管理raw,double free
|
|
277
|
+
|
|
278
|
+
// 危险场景2:release()后继续使用原unique_ptr
|
|
279
|
+
std::unique_ptr<Data> uptr = std::make_unique<Data>();
|
|
280
|
+
Data* raw = uptr.release();
|
|
281
|
+
uptr.reset(raw); // ❌ uptr重新管理raw,与裸指针所有权混乱
|
|
282
|
+
|
|
283
|
+
// 危险场景3:release()后对已释放的裸指针操作
|
|
284
|
+
std::unique_ptr<Data> uptr = std::make_unique<Data>();
|
|
285
|
+
Data* raw = uptr.release();
|
|
286
|
+
delete raw;
|
|
287
|
+
raw->DoSomething(); // ❌ use after free
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### 检测规则细化
|
|
291
|
+
|
|
292
|
+
**release()应该报的情况**:
|
|
293
|
+
- `release()`后裸指针被多个智能指针管理
|
|
294
|
+
- `release()`后裸指针被delete,但原智能指针还在管理
|
|
295
|
+
- `release()`后裸指针被reset回原智能指针
|
|
296
|
+
|
|
297
|
+
**release()不应该报的情况**:
|
|
298
|
+
- `release()`后裸指针正确管理(单一所有者)
|
|
299
|
+
- `release()`用于转移所有权给外部API
|
|
300
|
+
- `release()`作为函数返回值(调用者接管所有权)
|
|
301
|
+
- `release()`配合外部管理器使用
|
|
302
|
+
|
|
303
|
+
### 智能指针类型选择建议
|
|
304
|
+
|
|
305
|
+
根据实际代码实践,推荐:
|
|
306
|
+
|
|
307
|
+
1. **优先使用`std::make_unique/std::make_shared`**
|
|
308
|
+
- 避免`new`和裸指针
|
|
309
|
+
- 更安全,更高效
|
|
310
|
+
|
|
311
|
+
2. **统一使用一种智能指针类型**
|
|
312
|
+
- 在同一模块内统一使用`shared_ptr`或`unique_ptr`
|
|
313
|
+
- 减少混用风险
|
|
314
|
+
|
|
315
|
+
3. **使用`std::move`转移所有权**
|
|
316
|
+
- `unique_ptr`之间转移:`std::move(uptr)`
|
|
317
|
+
- `unique_ptr`到`shared_ptr`:`std::move(uptr)`
|
|
318
|
+
|
|
319
|
+
4. **明确函数签名的所有权语义**
|
|
320
|
+
- 返回智能指针:调用者获得所有权
|
|
321
|
+
- 参数为智能指针:函数获得所有权或共享
|
|
322
|
+
- 参数为裸指针:仅观察,不管理
|
|
323
|
+
## 测试用例
|
|
324
|
+
|
|
325
|
+
### 触发用例(应该报)
|
|
326
|
+
|
|
327
|
+
```cpp
|
|
328
|
+
// test_ResourceManagement_007_trigger.cpp
|
|
329
|
+
void trigger_bad_1() {
|
|
330
|
+
std::unique_ptr<Foo> uptr(new Foo());
|
|
331
|
+
Foo* raw = uptr.release(); // 应该报:release后裸指针管理
|
|
332
|
+
delete raw;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
void trigger_bad_2() {
|
|
336
|
+
std::shared_ptr<Foo> sptr = std::make_shared<Foo>();
|
|
337
|
+
Foo* raw = sptr.get();
|
|
338
|
+
delete raw; // 应该报:对get返回值delete
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
void trigger_bad_3() {
|
|
342
|
+
Foo* raw = new Foo();
|
|
343
|
+
std::unique_ptr<Foo> uptr(raw);
|
|
344
|
+
std::shared_ptr<Foo> sptr(raw); // 应该报:裸指针构造多个智能指针
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
void trigger_bad_4() {
|
|
348
|
+
Foo* raw = new Foo();
|
|
349
|
+
sptr<Foo> oh_sptr(raw);
|
|
350
|
+
std::shared_ptr<Foo> std_sptr(raw); // 应该报:sptr和shared_ptr混用
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
void trigger_bad_5() {
|
|
354
|
+
std::shared_ptr<Foo> sptr1 = std::make_shared<Foo>();
|
|
355
|
+
std::shared_ptr<Foo> sptr2(sptr1.get()); // 应该报:get构造新shared_ptr
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### 安全用例(不应该报)
|
|
360
|
+
|
|
361
|
+
```cpp
|
|
362
|
+
// test_ResourceManagement_007_safe.cpp
|
|
363
|
+
void safe_good_1() {
|
|
364
|
+
auto uptr = std::make_unique<Foo>(); // 安全:make_unique
|
|
365
|
+
uptr->DoSomething();
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
void safe_good_2() {
|
|
369
|
+
auto sptr = std::make_shared<Foo>(); // 安全:make_shared
|
|
370
|
+
Foo* raw = sptr.get();
|
|
371
|
+
raw->DoSomething(); // 安全:仅观察,不delete
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
void safe_good_3() {
|
|
375
|
+
std::unique_ptr<Foo> uptr = std::make_unique<Foo>();
|
|
376
|
+
std::shared_ptr<Foo> sptr = std::move(uptr); // 安全:转移所有权
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
void safe_good_4() {
|
|
380
|
+
sptr<Foo> ptr = new Foo(); // 安全:sptr管理
|
|
381
|
+
ptr->DoSomething();
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
void safe_good_5() {
|
|
385
|
+
std::shared_ptr<Foo> sptr1 = std::make_shared<Foo>();
|
|
386
|
+
std::shared_ptr<Foo> sptr2 = sptr1; // 安全:共享所有权
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// NOPROTECT: 测试代码
|
|
390
|
+
void noprotect_case() {
|
|
391
|
+
Foo* raw = new Foo();
|
|
392
|
+
std::unique_ptr<Foo> uptr(raw);
|
|
393
|
+
std::shared_ptr<Foo> sptr(raw);
|
|
394
|
+
}
|
|
395
|
+
```
|