@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,409 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule_id: "StabilityCodeReview_ResourceManagement_004"
|
|
3
|
+
name: "谨慎使用static_pointer_cast"
|
|
4
|
+
category: "资源管理"
|
|
5
|
+
severity: "MEDIUM"
|
|
6
|
+
language: ["cpp", "c++"]
|
|
7
|
+
author: "OH-Department7 Stability Team"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# 谨慎使用static_pointer_cast
|
|
11
|
+
|
|
12
|
+
## 问题描述
|
|
13
|
+
|
|
14
|
+
谨慎使用std::static_pointer_cast,子类转父类时几乎无需使用(shared_ptr支持隐式向上转换),父类转子类时必须要100%确定父类指针实际指向的是一个子类对象,否则会导致类型错误和未定义行为。
|
|
15
|
+
|
|
16
|
+
## 检测示例
|
|
17
|
+
|
|
18
|
+
### ❌ 问题代码
|
|
19
|
+
|
|
20
|
+
```cpp
|
|
21
|
+
// 场景1:子类转父类使用static_pointer_cast - 不必要
|
|
22
|
+
class Base { public: virtual ~Base() {} };
|
|
23
|
+
class Derived : public Base { public: void DerivedMethod() {} };
|
|
24
|
+
|
|
25
|
+
void UnnecessaryCast()
|
|
26
|
+
{
|
|
27
|
+
std::shared_ptr<Derived> derivedPtr = std::make_shared<Derived>();
|
|
28
|
+
|
|
29
|
+
// 错误:子类转父类不需要static_pointer_cast
|
|
30
|
+
std::shared_ptr<Base> basePtr = std::static_pointer_cast<Base>(derivedPtr);
|
|
31
|
+
|
|
32
|
+
// 正确:shared_ptr支持隐式向上转换
|
|
33
|
+
std::shared_ptr<Base> basePtr2 = derivedPtr; // 直接赋值即可
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 场景2:父类转子类未确认类型 - 危险
|
|
37
|
+
void DangerousDownCast(std::shared_ptr<Base> basePtr)
|
|
38
|
+
{
|
|
39
|
+
// 错误:未确认basePtr实际指向Derived对象
|
|
40
|
+
std::shared_ptr<Derived> derivedPtr = std::static_pointer_cast<Derived>(basePtr);
|
|
41
|
+
|
|
42
|
+
// 如果basePtr实际指向其他子类,这里会导致未定义行为
|
|
43
|
+
derivedPtr->DerivedMethod(); // 可能崩溃
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 场景3:在条件判断中静态向下转换 - 仍危险
|
|
47
|
+
void ConditionalDownCast(std::shared_ptr<Base> basePtr)
|
|
48
|
+
{
|
|
49
|
+
if (basePtr) {
|
|
50
|
+
// 错误:即使非空,也不保证是Derived类型
|
|
51
|
+
std::shared_ptr<Derived> derivedPtr = std::static_pointer_cast<Derived>(basePtr);
|
|
52
|
+
derivedPtr->DerivedMethod();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 场景4:链式static_pointer_cast - 更危险
|
|
57
|
+
class Base {};
|
|
58
|
+
class Middle : public Base {};
|
|
59
|
+
class Leaf : public Middle {};
|
|
60
|
+
|
|
61
|
+
void ChainCast(std::shared_ptr<Base> basePtr)
|
|
62
|
+
{
|
|
63
|
+
// 错误:链式转换,每一步都有类型错误风险
|
|
64
|
+
std::shared_ptr<Middle> middlePtr = std::static_pointer_cast<Middle>(basePtr);
|
|
65
|
+
std::shared_ptr<Leaf> leafPtr = std::static_pointer_cast<Leaf>(middlePtr);
|
|
66
|
+
|
|
67
|
+
// 如果basePtr不是Leaf类型,多层转换后崩溃
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// 场景5:在容器遍历中误用
|
|
71
|
+
void ContainerCastMisuse()
|
|
72
|
+
{
|
|
73
|
+
std::vector<std::shared_ptr<Base>> objects;
|
|
74
|
+
objects.push_back(std::make_shared<Derived>());
|
|
75
|
+
objects.push_back(std::make_shared<OtherDerived>());
|
|
76
|
+
|
|
77
|
+
for (auto& obj : objects) {
|
|
78
|
+
// 错误:假设所有对象都是Derived类型
|
|
79
|
+
std::shared_ptr<Derived> derived = std::static_pointer_cast<Derived>(obj);
|
|
80
|
+
derived->DerivedMethod(); // OtherDerived对象会崩溃
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// 场景6:工厂模式误用
|
|
85
|
+
std::shared_ptr<Base> CreateObject(int type)
|
|
86
|
+
{
|
|
87
|
+
if (type == 1) {
|
|
88
|
+
return std::make_shared<Derived>();
|
|
89
|
+
} else {
|
|
90
|
+
return std::make_shared<OtherDerived>();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
void FactoryCastMisuse(int type)
|
|
95
|
+
{
|
|
96
|
+
auto obj = CreateObject(type);
|
|
97
|
+
|
|
98
|
+
// 错误:未检查type,直接向下转换
|
|
99
|
+
std::shared_ptr<Derived> derived = std::static_pointer_cast<Derived>(obj);
|
|
100
|
+
derived->DerivedMethod();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// 场景7:多继承情况下的static_pointer_cast - 更复杂
|
|
104
|
+
class BaseA { public: virtual ~BaseA() {} };
|
|
105
|
+
class BaseB { public: virtual ~BaseB() {} };
|
|
106
|
+
class MultiDerived : public BaseA, public BaseB {};
|
|
107
|
+
|
|
108
|
+
void MultiInheritanceCast(std::shared_ptr<BaseA> baseAPtr)
|
|
109
|
+
{
|
|
110
|
+
// 错误:多继承情况下static_pointer_cast可能导致指针偏移错误
|
|
111
|
+
std::shared_ptr<BaseB> baseBPtr = std::static_pointer_cast<BaseB>(baseAPtr);
|
|
112
|
+
// 即使对象是MultiDerived,这样转换可能导致错误的指针值
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 场景8:回调函数中误用
|
|
116
|
+
void CallbackCast(std::shared_ptr<Base> basePtr)
|
|
117
|
+
{
|
|
118
|
+
auto callback = [basePtr]() {
|
|
119
|
+
// 错误:回调中假设类型
|
|
120
|
+
auto derived = std::static_pointer_cast<Derived>(basePtr);
|
|
121
|
+
derived->DerivedMethod();
|
|
122
|
+
};
|
|
123
|
+
callback();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 场景9:工厂返回后直接转换
|
|
127
|
+
class Factory {
|
|
128
|
+
public:
|
|
129
|
+
static std::shared_ptr<Base> Create() {
|
|
130
|
+
return std::make_shared<Derived>();
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
void DirectCast()
|
|
135
|
+
{
|
|
136
|
+
auto obj = Factory::Create();
|
|
137
|
+
|
|
138
|
+
// 错误:即使Create返回Derived,依赖实现细节
|
|
139
|
+
std::shared_ptr<Derived> derived = std::static_pointer_cast<Derived>(obj);
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### ✅ 修复方案
|
|
144
|
+
|
|
145
|
+
```cpp
|
|
146
|
+
// 修复场景1:使用隐式向上转换
|
|
147
|
+
class Base { public: virtual ~Base() {} };
|
|
148
|
+
class Derived : public Base { public: void DerivedMethod() {} };
|
|
149
|
+
|
|
150
|
+
void UpCastCorrect()
|
|
151
|
+
{
|
|
152
|
+
std::shared_ptr<Derived> derivedPtr = std::make_shared<Derived>();
|
|
153
|
+
|
|
154
|
+
// 正确:隐式向上转换
|
|
155
|
+
std::shared_ptr<Base> basePtr = derivedPtr; // 不需要static_pointer_cast
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// 修复场景2:使用dynamic_pointer_cast安全向下转换
|
|
159
|
+
void SafeDownCast(std::shared_ptr<Base> basePtr)
|
|
160
|
+
{
|
|
161
|
+
// 正确:使用dynamic_pointer_cast检查类型
|
|
162
|
+
std::shared_ptr<Derived> derivedPtr = std::dynamic_pointer_cast<Derived>(basePtr);
|
|
163
|
+
|
|
164
|
+
if (derivedPtr) {
|
|
165
|
+
// 类型确认后安全使用
|
|
166
|
+
derivedPtr->DerivedMethod();
|
|
167
|
+
} else {
|
|
168
|
+
LOGE("basePtr is not a Derived object");
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// 修复场景3:添加类型标识检查
|
|
173
|
+
class Base {
|
|
174
|
+
public:
|
|
175
|
+
virtual ~Base() {}
|
|
176
|
+
virtual int GetType() const = 0;
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
class Derived : public Base {
|
|
180
|
+
public:
|
|
181
|
+
int GetType() const override { return TYPE_DERIVED; }
|
|
182
|
+
void DerivedMethod() {}
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
void TypeCheckDownCast(std::shared_ptr<Base> basePtr)
|
|
186
|
+
{
|
|
187
|
+
if (basePtr && basePtr->GetType() == TYPE_DERIVED) {
|
|
188
|
+
// 有类型检查后可以安全使用static_pointer_cast
|
|
189
|
+
std::shared_ptr<Derived> derivedPtr = std::static_pointer_cast<Derived>(basePtr);
|
|
190
|
+
derivedPtr->DerivedMethod();
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// 修复场景4:使用dynamic_pointer_cast替代链式转换
|
|
195
|
+
void ChainCastCorrect(std::shared_ptr<Base> basePtr)
|
|
196
|
+
{
|
|
197
|
+
// 正确:直接dynamic_pointer_cast到目标类型
|
|
198
|
+
std::shared_ptr<Leaf> leafPtr = std::dynamic_pointer_cast<Leaf>(basePtr);
|
|
199
|
+
|
|
200
|
+
if (leafPtr) {
|
|
201
|
+
leafPtr->LeafMethod();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// 修复场景5:容器中逐个检查类型
|
|
206
|
+
void ContainerCastCorrect()
|
|
207
|
+
{
|
|
208
|
+
std::vector<std::shared_ptr<Base>> objects;
|
|
209
|
+
|
|
210
|
+
for (auto& obj : objects) {
|
|
211
|
+
// 正确:逐个检查类型
|
|
212
|
+
std::shared_ptr<Derived> derived = std::dynamic_pointer_cast<Derived>(obj);
|
|
213
|
+
if (derived) {
|
|
214
|
+
derived->DerivedMethod();
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// 修复场景6:工厂模式类型检查
|
|
220
|
+
void FactoryCastCorrect(int type)
|
|
221
|
+
{
|
|
222
|
+
auto obj = CreateObject(type);
|
|
223
|
+
|
|
224
|
+
if (type == 1) {
|
|
225
|
+
// 正确:根据type确认类型
|
|
226
|
+
std::shared_ptr<Derived> derived = std::static_pointer_cast<Derived>(obj);
|
|
227
|
+
derived->DerivedMethod();
|
|
228
|
+
} else {
|
|
229
|
+
// 处理其他类型
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// 修复场景7:多继承使用dynamic_pointer_cast
|
|
234
|
+
class BaseA { public: virtual ~BaseA() {} };
|
|
235
|
+
class BaseB { public: virtual ~BaseB() {} };
|
|
236
|
+
class MultiDerived : public BaseA, public BaseB {};
|
|
237
|
+
|
|
238
|
+
void MultiInheritanceCastCorrect(std::shared_ptr<BaseA> baseAPtr)
|
|
239
|
+
{
|
|
240
|
+
// 正确:使用dynamic_pointer_cast处理多继承
|
|
241
|
+
std::shared_ptr<MultiDerived> multiPtr = std::dynamic_pointer_cast<MultiDerived>(baseAPtr);
|
|
242
|
+
|
|
243
|
+
if (multiPtr) {
|
|
244
|
+
std::shared_ptr<BaseB> baseBPtr = multiPtr; // 隐式转换
|
|
245
|
+
baseBPtr->BaseBMethod();
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// 修复场景8:回调中类型检查
|
|
250
|
+
void CallbackCastCorrect(std::shared_ptr<Base> basePtr)
|
|
251
|
+
{
|
|
252
|
+
auto callback = [basePtr]() {
|
|
253
|
+
// 正确:回调中使用dynamic_pointer_cast检查
|
|
254
|
+
auto derived = std::dynamic_pointer_cast<Derived>(basePtr);
|
|
255
|
+
if (derived) {
|
|
256
|
+
derived->DerivedMethod();
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
callback();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// 修复场景9:使用模板工厂明确类型
|
|
263
|
+
template<typename T>
|
|
264
|
+
class TypedFactory {
|
|
265
|
+
public:
|
|
266
|
+
static std::shared_ptr<T> Create() {
|
|
267
|
+
return std::make_shared<T>();
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
void DirectCastCorrect()
|
|
272
|
+
{
|
|
273
|
+
// 正确:工厂直接返回具体类型
|
|
274
|
+
auto derived = TypedFactory<Derived>::Create();
|
|
275
|
+
derived->DerivedMethod();
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// 修复场景10:必要时注释说明
|
|
279
|
+
void DocumentedCast(std::shared_ptr<Base> basePtr)
|
|
280
|
+
{
|
|
281
|
+
// 当100%确定类型时,可以使用static_pointer_cast但需注释
|
|
282
|
+
// 此处basePtr由CreateDerived函数返回,必定是Derived类型
|
|
283
|
+
std::shared_ptr<Derived> derivedPtr = std::static_pointer_cast<Derived>(basePtr);
|
|
284
|
+
derivedPtr->DerivedMethod();
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// 修复场景11:最佳实践 - 避免向下转换
|
|
288
|
+
class Base {
|
|
289
|
+
public:
|
|
290
|
+
virtual ~Base() {}
|
|
291
|
+
virtual void Process() = 0; // 使用虚函数代替向下转换
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
class Derived : public Base {
|
|
295
|
+
public:
|
|
296
|
+
void Process() override { DerivedMethod(); }
|
|
297
|
+
private:
|
|
298
|
+
void DerivedMethod() {}
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
void BestPractice(std::shared_ptr<Base> basePtr)
|
|
302
|
+
{
|
|
303
|
+
// 正确:使用虚函数,无需向下转换
|
|
304
|
+
basePtr->Process(); // 自动调用正确的实现
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## 检测范围
|
|
309
|
+
|
|
310
|
+
检查以下模式:
|
|
311
|
+
|
|
312
|
+
- `std::static_pointer_cast<Derived>(basePtr)` 向下转换
|
|
313
|
+
- `std::static_pointer_cast<Base>(derivedPtr)` 向上转换(不必要)
|
|
314
|
+
- 链式static_pointer_cast调用
|
|
315
|
+
- 无类型检查的static_pointer_cast
|
|
316
|
+
|
|
317
|
+
## 检测要点
|
|
318
|
+
|
|
319
|
+
1. 识别`std::static_pointer_cast`调用
|
|
320
|
+
2. 检查是否是向上转换(子类到父类)- 不必要
|
|
321
|
+
3. 检查是否是向下转换(父类到子类)- 需确认类型
|
|
322
|
+
4. 检查是否有类型检查机制(dynamic_pointer_cast、类型标识)
|
|
323
|
+
5. 识别链式转换的风险
|
|
324
|
+
|
|
325
|
+
## 风险流分析(RiskFlow)
|
|
326
|
+
|
|
327
|
+
- **RISK_SOURCE**:父类指针可能指向错误的子类类型
|
|
328
|
+
- **RISK_TYPE**:类型错误导致未定义行为
|
|
329
|
+
- **RISK_PATH**:static_pointer_cast -> 错误类型 -> 调用不存在的方法 -> 崩溃
|
|
330
|
+
- **IMPACT_POINT**:程序崩溃、数据损坏
|
|
331
|
+
|
|
332
|
+
## 影响分析(ImpactAnalysis)
|
|
333
|
+
|
|
334
|
+
- **Trigger**:父类指针向下转换为错误的子类类型
|
|
335
|
+
- **Propagation**:调用不存在的成员函数或访问错误内存
|
|
336
|
+
- **Consequence**:未定义行为、程序崩溃、数据损坏
|
|
337
|
+
- **Mitigation**:使用dynamic_pointer_cast检查类型,或使用虚函数避免转换
|
|
338
|
+
|
|
339
|
+
## 误报排除
|
|
340
|
+
|
|
341
|
+
| 场景 | 识别特征 | 处理方式 |
|
|
342
|
+
|------|----------|----------|
|
|
343
|
+
| 向上转换 | 目标类型是基类 | 提示不必要而非错误 |
|
|
344
|
+
| 有类型检查 | dynamic_cast或类型标识检查 | 不报 |
|
|
345
|
+
| 虚函数设计 | 使用虚函数避免转换 | 不报 |
|
|
346
|
+
| 文档说明 | 有注释说明100%确定类型 | 可能不报 |
|
|
347
|
+
| NOPROTECT标记 | 有 // NOPROTECT 注释 | 不报 |
|
|
348
|
+
## 测试用例
|
|
349
|
+
|
|
350
|
+
### 触发用例(应该报)
|
|
351
|
+
|
|
352
|
+
```cpp
|
|
353
|
+
// test_ResourceManagement_004_trigger.cpp
|
|
354
|
+
class Base { public: virtual ~Base() {} };
|
|
355
|
+
class Derived : public Base {};
|
|
356
|
+
|
|
357
|
+
void trigger_bad_1(std::shared_ptr<Base> basePtr)
|
|
358
|
+
{
|
|
359
|
+
auto derived = std::static_pointer_cast<Derived>(basePtr); // 应该报:向下转换无检查
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
void trigger_bad_2()
|
|
363
|
+
{
|
|
364
|
+
auto derived = std::make_shared<Derived>();
|
|
365
|
+
auto base = std::static_pointer_cast<Base>(derived); // 应该报:向上转换不必要
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
void trigger_bad_3(std::shared_ptr<Base> basePtr)
|
|
369
|
+
{
|
|
370
|
+
if (basePtr) {
|
|
371
|
+
auto derived = std::static_pointer_cast<Derived>(basePtr); // 应该报:仅检查非空不够
|
|
372
|
+
derived->Method();
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### 安全用例(不应该报)
|
|
378
|
+
|
|
379
|
+
```cpp
|
|
380
|
+
// test_ResourceManagement_004_safe.cpp
|
|
381
|
+
void safe_good_1(std::shared_ptr<Base> basePtr)
|
|
382
|
+
{
|
|
383
|
+
auto derived = std::dynamic_pointer_cast<Derived>(basePtr); // 安全:dynamic检查
|
|
384
|
+
if (derived) {
|
|
385
|
+
derived->Method();
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
void safe_good_2()
|
|
390
|
+
{
|
|
391
|
+
auto derived = std::make_shared<Derived>();
|
|
392
|
+
std::shared_ptr<Base> base = derived; // 安全:隐式向上转换
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
void safe_good_3(std::shared_ptr<Base> basePtr)
|
|
396
|
+
{
|
|
397
|
+
if (basePtr && basePtr->GetType() == TYPE_DERIVED) { // 安全:有类型检查
|
|
398
|
+
auto derived = std::static_pointer_cast<Derived>(basePtr);
|
|
399
|
+
derived->Method();
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// NOPROTECT: 特殊场景
|
|
404
|
+
// NOPROTECT: 100%确定类型
|
|
405
|
+
void noprotect_case(std::shared_ptr<Base> basePtr)
|
|
406
|
+
{
|
|
407
|
+
auto derived = std::static_pointer_cast<Derived>(basePtr);
|
|
408
|
+
}
|
|
409
|
+
```
|