@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,420 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule_id: "StabilityCodeReview_ResourceManagement_003"
|
|
3
|
+
name: "禁止智能指针get初始化另一个智能指针"
|
|
4
|
+
category: "资源管理"
|
|
5
|
+
severity: "CRITICAL"
|
|
6
|
+
language: ["cpp", "c++"]
|
|
7
|
+
author: "OH-Department7 Stability Team"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# 禁止智能指针get初始化另一个智能指针
|
|
11
|
+
|
|
12
|
+
## 问题描述
|
|
13
|
+
|
|
14
|
+
禁止使用get初始化或赋值给另一个智能指针。从智能指针get()获取的裸指针再用来创建另一个智能指针,会导致两个智能指针管理同一个资源,析构时产生重复释放,造成程序崩溃。
|
|
15
|
+
|
|
16
|
+
## 检测示例
|
|
17
|
+
|
|
18
|
+
### ❌ 问题代码
|
|
19
|
+
|
|
20
|
+
```cpp
|
|
21
|
+
// 场景1:get()创建另一个shared_ptr - 双重释放
|
|
22
|
+
void ProcessData()
|
|
23
|
+
{
|
|
24
|
+
std::shared_ptr<Data> ptr1 = std::make_shared<Data>();
|
|
25
|
+
|
|
26
|
+
// 错误:用get()创建另一个shared_ptr
|
|
27
|
+
std::shared_ptr<Data> ptr2(ptr1.get()); // 两个shared_ptr管理同一资源
|
|
28
|
+
|
|
29
|
+
// ptr1析构释放资源
|
|
30
|
+
// ptr2析构再次释放同一资源 -> 双重释放崩溃
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// 场景2:get()赋值给另一个shared_ptr
|
|
34
|
+
void HandleResource()
|
|
35
|
+
{
|
|
36
|
+
std::shared_ptr<Resource> original = std::make_shared<Resource>();
|
|
37
|
+
|
|
38
|
+
// 错误:用get()赋值
|
|
39
|
+
std::shared_ptr<Resource> copy;
|
|
40
|
+
copy.reset(original.get()); // 双重管理
|
|
41
|
+
|
|
42
|
+
// 两个shared_ptr都会尝试释放
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// 场景3:函数返回get()指针被外部创建智能指针
|
|
46
|
+
std::shared_ptr<File> GetFile()
|
|
47
|
+
{
|
|
48
|
+
static std::shared_ptr<File> filePtr = std::make_shared<File>();
|
|
49
|
+
return filePtr; // 正确:共享所有权
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
void UseFile()
|
|
53
|
+
{
|
|
54
|
+
std::shared_ptr<File> ptr1 = GetFile(); // 正确
|
|
55
|
+
|
|
56
|
+
// 错误:用get()创建新的智能指针
|
|
57
|
+
std::shared_ptr<File> ptr2(GetFile().get()); // 双重管理,崩溃风险
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// 场景4:get()初始化unique_ptr - 更危险
|
|
61
|
+
void ProcessUnique()
|
|
62
|
+
{
|
|
63
|
+
std::shared_ptr<Data> sharedPtr = std::make_shared<Data>();
|
|
64
|
+
|
|
65
|
+
// 错误:shared_ptr的get()初始化unique_ptr
|
|
66
|
+
std::unique_ptr<Data> uniquePtr(sharedPtr.get()); // unique_ptr会释放
|
|
67
|
+
|
|
68
|
+
// sharedPtr析构时再次释放 -> 崩溃
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 场景5:成员函数返回get()被外部管理
|
|
72
|
+
class ResourceManager {
|
|
73
|
+
private:
|
|
74
|
+
std::shared_ptr<Resource> resource_;
|
|
75
|
+
|
|
76
|
+
public:
|
|
77
|
+
Resource* GetRaw() {
|
|
78
|
+
return resource_.get(); // 返回裸指针
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
void UseResource()
|
|
83
|
+
{
|
|
84
|
+
ResourceManager mgr;
|
|
85
|
+
|
|
86
|
+
// 错误:用返回的裸指针创建智能指针
|
|
87
|
+
std::shared_ptr<Resource> ptr(mgr.GetRaw()); // mgr.resource_析构时释放一次
|
|
88
|
+
// ptr析构时再释放一次 -> 崩溃
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 场景6:get()用于构造函数参数
|
|
92
|
+
class DataProcessor {
|
|
93
|
+
public:
|
|
94
|
+
DataProcessor(std::shared_ptr<Data> data) {
|
|
95
|
+
// 错误:假设调用者传入get()的结果
|
|
96
|
+
// 构造函数应该接收shared_ptr本身,而非裸指针
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
void Process()
|
|
101
|
+
{
|
|
102
|
+
std::shared_ptr<Data> data = std::make_shared<Data>();
|
|
103
|
+
|
|
104
|
+
// 错误:用get()构造
|
|
105
|
+
DataProcessor processor(std::shared_ptr<Data>(data.get()));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// 场景7:weak_ptr误用
|
|
109
|
+
void WeakPtrMisuse()
|
|
110
|
+
{
|
|
111
|
+
std::shared_ptr<Data> strongPtr = std::make_shared<Data>();
|
|
112
|
+
std::weak_ptr<Data> weakPtr = strongPtr;
|
|
113
|
+
|
|
114
|
+
// 错误:用weak_ptr的lock().get()
|
|
115
|
+
if (auto locked = weakPtr.lock()) {
|
|
116
|
+
std::shared_ptr<Data> another(locked.get()); // 双重管理
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 场景8:容器中误用
|
|
121
|
+
void ContainerMisuse()
|
|
122
|
+
{
|
|
123
|
+
std::vector<std::shared_ptr<Data>> vec;
|
|
124
|
+
vec.push_back(std::make_shared<Data>());
|
|
125
|
+
|
|
126
|
+
// 错误:从容器取get()创建新的智能指针
|
|
127
|
+
std::shared_ptr<Data> ptr(vec[0].get()); // vec中的shared_ptr和ptr双重管理
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### ✅ 修复方案
|
|
132
|
+
|
|
133
|
+
```cpp
|
|
134
|
+
// 修复场景1:正确共享所有权
|
|
135
|
+
void ProcessData()
|
|
136
|
+
{
|
|
137
|
+
std::shared_ptr<Data> ptr1 = std::make_shared<Data>();
|
|
138
|
+
|
|
139
|
+
// 正确:直接拷贝shared_ptr,共享所有权
|
|
140
|
+
std::shared_ptr<Data> ptr2 = ptr1; // 引用计数增加
|
|
141
|
+
|
|
142
|
+
// 只在最后一个shared_ptr析构时释放
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// 修复场景2:正确赋值
|
|
146
|
+
void HandleResource()
|
|
147
|
+
{
|
|
148
|
+
std::shared_ptr<Resource> original = std::make_shared<Resource>();
|
|
149
|
+
|
|
150
|
+
// 正确:直接赋值
|
|
151
|
+
std::shared_ptr<Resource> copy = original; // 共享所有权
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 修复场景3:返回shared_ptr本身
|
|
155
|
+
std::shared_ptr<File> GetFile()
|
|
156
|
+
{
|
|
157
|
+
static std::shared_ptr<File> filePtr = std::make_shared<File>();
|
|
158
|
+
return filePtr; // 正确:返回shared_ptr
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
void UseFile()
|
|
162
|
+
{
|
|
163
|
+
std::shared_ptr<File> ptr = GetFile(); // 正确:共享所有权
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// 修复场景4:不要混合管理
|
|
167
|
+
void ProcessUnique()
|
|
168
|
+
{
|
|
169
|
+
// 如果需要unique_ptr,直接创建
|
|
170
|
+
std::unique_ptr<Data> uniquePtr = std::make_unique<Data>();
|
|
171
|
+
|
|
172
|
+
// 如果需要共享,用shared_ptr
|
|
173
|
+
std::shared_ptr<Data> sharedPtr = std::make_shared<Data>();
|
|
174
|
+
|
|
175
|
+
// 不要混用
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// 修复场景5:返回shared_ptr而非裸指针
|
|
179
|
+
class ResourceManager {
|
|
180
|
+
private:
|
|
181
|
+
std::shared_ptr<Resource> resource_;
|
|
182
|
+
|
|
183
|
+
public:
|
|
184
|
+
std::shared_ptr<Resource> GetShared() {
|
|
185
|
+
return resource_; // 正确:返回shared_ptr
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
Resource* GetRaw() {
|
|
189
|
+
return resource_.get(); // 仅用于观察,不管理
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
void UseResource()
|
|
194
|
+
{
|
|
195
|
+
ResourceManager mgr;
|
|
196
|
+
|
|
197
|
+
// 正确:获取shared_ptr共享所有权
|
|
198
|
+
std::shared_ptr<Resource> ptr = mgr.GetShared();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// 修复场景6:直接传递shared_ptr
|
|
202
|
+
class DataProcessor {
|
|
203
|
+
public:
|
|
204
|
+
DataProcessor(std::shared_ptr<Data> data) : data_(data) {}
|
|
205
|
+
private:
|
|
206
|
+
std::shared_ptr<Data> data_;
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
void Process()
|
|
210
|
+
{
|
|
211
|
+
std::shared_ptr<Data> data = std::make_shared<Data>();
|
|
212
|
+
|
|
213
|
+
// 正确:直接传递shared_ptr
|
|
214
|
+
DataProcessor processor(data);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// 修复场景7:正确使用weak_ptr
|
|
218
|
+
void WeakPtrCorrect()
|
|
219
|
+
{
|
|
220
|
+
std::shared_ptr<Data> strongPtr = std::make_shared<Data>();
|
|
221
|
+
std::weak_ptr<Data> weakPtr = strongPtr;
|
|
222
|
+
|
|
223
|
+
// 正确:lock()返回的shared_ptr直接使用
|
|
224
|
+
if (auto locked = weakPtr.lock()) {
|
|
225
|
+
// 直接使用locked,不要再用get()创建新的
|
|
226
|
+
locked->Process();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// 修复场景8:容器正确使用
|
|
231
|
+
void ContainerCorrect()
|
|
232
|
+
{
|
|
233
|
+
std::vector<std::shared_ptr<Data>> vec;
|
|
234
|
+
vec.push_back(std::make_shared<Data>());
|
|
235
|
+
|
|
236
|
+
// 正确:直接拷贝shared_ptr
|
|
237
|
+
std::shared_ptr<Data> ptr = vec[0]; // 共享所有权
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// 修复场景9:明确所有权转移
|
|
241
|
+
void TransferOwnership()
|
|
242
|
+
{
|
|
243
|
+
std::unique_ptr<Data> uniquePtr = std::make_unique<Data>();
|
|
244
|
+
|
|
245
|
+
// 如果需要转移所有权给shared_ptr
|
|
246
|
+
std::shared_ptr<Data> sharedPtr(std::move(uniquePtr)); // 正确:move转移
|
|
247
|
+
|
|
248
|
+
// uniquePtr现在为空,sharedPtr独占所有权
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// 修复场景10:观察者模式正确使用
|
|
252
|
+
void ObserverPattern()
|
|
253
|
+
{
|
|
254
|
+
std::shared_ptr<Data> data = std::make_shared<Data>();
|
|
255
|
+
|
|
256
|
+
// 观察者只使用裸指针观察,不管理
|
|
257
|
+
Data* observer = data.get();
|
|
258
|
+
observer->Inspect(); // 正确:仅观察
|
|
259
|
+
|
|
260
|
+
// 不要用observer创建智能指针
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## 检测范围
|
|
265
|
+
|
|
266
|
+
检查以下模式:
|
|
267
|
+
|
|
268
|
+
- `std::shared_ptr<T>(ptr.get())`
|
|
269
|
+
- `std::unique_ptr<T>(ptr.get())`
|
|
270
|
+
- `ptr.reset(other.get())`
|
|
271
|
+
- `std::shared_ptr<T>(obj->GetRaw())`(GetRaw返回get())
|
|
272
|
+
- `make_shared<T>(ptr.get())`
|
|
273
|
+
- `make_unique<T>(ptr.get())`
|
|
274
|
+
|
|
275
|
+
## 检测要点
|
|
276
|
+
|
|
277
|
+
1. 识别`get()`方法调用
|
|
278
|
+
2. 检查`get()`的结果是否用于创建智能指针
|
|
279
|
+
3. 检测智能指针构造函数中使用`get()`的结果
|
|
280
|
+
4. 检测`reset()`方法中使用`get()`的结果
|
|
281
|
+
5. 排除合理使用的场景(如观察者模式)
|
|
282
|
+
|
|
283
|
+
## 风险流分析(RiskFlow)
|
|
284
|
+
|
|
285
|
+
- **RISK_SOURCE**:智能指针get()返回的裸指针
|
|
286
|
+
- **RISK_TYPE**:双重释放
|
|
287
|
+
- **RISK_PATH**:get() -> 新智能指针管理 -> 两个智能指针析构 -> 双重释放崩溃
|
|
288
|
+
- **IMPACT_POINT**:程序崩溃、数据损坏
|
|
289
|
+
|
|
290
|
+
## 影响分析(ImpactAnalysis)
|
|
291
|
+
|
|
292
|
+
- **Trigger**:使用get()创建另一个智能指针
|
|
293
|
+
- **Propagation**:两个智能指针管理同一资源,析构时重复释放
|
|
294
|
+
- **Consequence**:程序崩溃、堆损坏、数据丢失
|
|
295
|
+
- **Mitigation**:正确共享所有权(拷贝shared_ptr)或使用std::move转移所有权
|
|
296
|
+
|
|
297
|
+
## 误报排除
|
|
298
|
+
|
|
299
|
+
| 场景 | 识别特征 | 处理方式 |
|
|
300
|
+
|------|----------|----------|
|
|
301
|
+
| 观察者模式 | get()用于观察不创建智能指针 | 不报 |
|
|
302
|
+
| 转移所有权 | std::move(unique_ptr)到shared_ptr | 不报 |
|
|
303
|
+
| 老代码兼容 | 用于调用需要裸指针的API | 需检查不创建智能指针 |
|
|
304
|
+
| NOPROTECT标记 | 有 // NOPROTECT 注释 | 不报 |
|
|
305
|
+
| 第三方库 | 位于 third_party 目录 | 白名单排除 |
|
|
306
|
+
|
|
307
|
+
### get()的正确使用场景区分
|
|
308
|
+
|
|
309
|
+
`get()`方法本身是安全的,关键在于返回值的使用方式:
|
|
310
|
+
|
|
311
|
+
#### ✅ 安全场景(get()用于观察)
|
|
312
|
+
|
|
313
|
+
```cpp
|
|
314
|
+
// 安全场景1:调用需要裸指针的API
|
|
315
|
+
std::shared_ptr<Data> data = std::make_shared<Data>();
|
|
316
|
+
LegacyAPI(data.get()); // 安全:仅观察,不创建新智能指针
|
|
317
|
+
|
|
318
|
+
// 安全场景2:判断指针有效性
|
|
319
|
+
std::shared_ptr<Node> node = GetNode();
|
|
320
|
+
if (node.get() != nullptr) { // 安全:仅判断有效性
|
|
321
|
+
node->Process();
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// 安全场景3:传递给不管理所有权的函数
|
|
325
|
+
void ObserverFunction(Data* rawPtr) {
|
|
326
|
+
rawPtr->Inspect(); // 仅观察,不delete,不创建智能指针
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
std::shared_ptr<Data> data = std::make_shared<Data>();
|
|
330
|
+
ObserverFunction(data.get()); // 安全:函数不获取所有权
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
#### ❌ 危险场景(get()创建新智能指针)
|
|
334
|
+
|
|
335
|
+
```cpp
|
|
336
|
+
// 危险场景1:用get()创建新的shared_ptr
|
|
337
|
+
std::shared_ptr<Data> ptr1 = std::make_shared<Data>();
|
|
338
|
+
std::shared_ptr<Data> ptr2(ptr1.get()); // ❌ 双重管理,应报
|
|
339
|
+
|
|
340
|
+
// 危险场景2:用get()赋值给另一个shared_ptr
|
|
341
|
+
std::shared_ptr<Data> ptr1 = std::make_shared<Data>();
|
|
342
|
+
std::shared_ptr<Data> ptr2;
|
|
343
|
+
ptr2.reset(ptr1.get()); // ❌ 双重管理,应报
|
|
344
|
+
|
|
345
|
+
// 危险场景3:用get()创建unique_ptr
|
|
346
|
+
std::shared_ptr<Data> sharedPtr = std::make_shared<Data>();
|
|
347
|
+
std::unique_ptr<Data> uniquePtr(sharedPtr.get()); // ❌ 混用,应报
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### 检测规则细化
|
|
351
|
+
|
|
352
|
+
**应该报的情况**:
|
|
353
|
+
- `std::shared_ptr<T>(existingPtr.get())` - 构造函数参数
|
|
354
|
+
- `std::unique_ptr<T>(existingPtr.get())` - 构造函数参数
|
|
355
|
+
- `newPtr.reset(existingPtr.get())` - reset参数
|
|
356
|
+
- `std::make_shared<T>(existingPtr.get())` - make_shared参数
|
|
357
|
+
- `std::make_unique<T>(existingPtr.get())` - make_unique参数
|
|
358
|
+
|
|
359
|
+
**不应该报的情况**:
|
|
360
|
+
- `LegacyAPI(ptr.get())` - API调用,不创建智能指针
|
|
361
|
+
- `if (ptr.get() != nullptr)` - 仅判断有效性
|
|
362
|
+
- `ObserverFunction(ptr.get())` - 函数参数,观察用途
|
|
363
|
+
- `ptr.get()->Method()` - 通过裸指针调用方法,不创建智能指针
|
|
364
|
+
## 测试用例
|
|
365
|
+
|
|
366
|
+
### 触发用例(应该报)
|
|
367
|
+
|
|
368
|
+
```cpp
|
|
369
|
+
// test_ResourceManagement_003_trigger.cpp
|
|
370
|
+
void trigger_bad_1()
|
|
371
|
+
{
|
|
372
|
+
auto ptr1 = std::make_shared<Data>();
|
|
373
|
+
std::shared_ptr<Data> ptr2(ptr1.get()); // 应该报:双重管理
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
void trigger_bad_2()
|
|
377
|
+
{
|
|
378
|
+
std::shared_ptr<Resource> original = std::make_shared<Resource>();
|
|
379
|
+
std::shared_ptr<Resource> copy;
|
|
380
|
+
copy.reset(original.get()); // 应该报:双重管理
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
void trigger_bad_3()
|
|
384
|
+
{
|
|
385
|
+
std::shared_ptr<Data> sharedPtr = std::make_shared<Data>();
|
|
386
|
+
std::unique_ptr<Data> uniquePtr(sharedPtr.get()); // 应该报:混用管理
|
|
387
|
+
}
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### 安全用例(不应该报)
|
|
391
|
+
|
|
392
|
+
```cpp
|
|
393
|
+
// test_ResourceManagement_003_safe.cpp
|
|
394
|
+
void safe_good_1()
|
|
395
|
+
{
|
|
396
|
+
auto ptr1 = std::make_shared<Data>();
|
|
397
|
+
std::shared_ptr<Data> ptr2 = ptr1; // 安全:共享所有权
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
void safe_good_2()
|
|
401
|
+
{
|
|
402
|
+
auto uniquePtr = std::make_unique<Data>();
|
|
403
|
+
std::shared_ptr<Data> sharedPtr(std::move(uniquePtr)); // 安全:转移所有权
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
void safe_good_3()
|
|
407
|
+
{
|
|
408
|
+
auto data = std::make_shared<Data>();
|
|
409
|
+
Data* raw = data.get(); // 安全:仅观察
|
|
410
|
+
raw->Inspect(); // 不创建智能指针
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// NOPROTECT: 特殊场景
|
|
414
|
+
// NOPROTECT: 测试代码
|
|
415
|
+
void noprotect_case()
|
|
416
|
+
{
|
|
417
|
+
auto ptr1 = std::make_shared<Data>();
|
|
418
|
+
std::shared_ptr<Data> ptr2(ptr1.get());
|
|
419
|
+
}
|
|
420
|
+
```
|