题目描述
华为OD-E卷中的一道题目是关于静态代码扫描服务的。假设你正在开发一个静态代码扫描工具,该工具可以扫描代码并识别出潜在的缺陷或不符合编码规范的地方。题目要求你实现一个基础版本,能够扫描给定的代码片段,并识别出其中的一些常见缺陷,例如:
- 空指针访问
- 数组越界访问
- 未处理的异常
- 不必要的对象创建
你需要实现一个函数,该函数接收代码片段作为输入,并返回一个包含识别到的缺陷列表的字符串。
思路解析
为了实现这个静态代码扫描工具的基础版本,我们可以采取以下步骤:
- 词法分析:解析代码片段,提取出关键字、变量名、操作符等。
- 语法分析:根据提取的词法单元,构建语法树(AST),理解代码的结构。
- 规则匹配:定义一组规则,用于识别上述提到的常见缺陷。
- 缺陷报告:遍历语法树,应用规则匹配,收集并报告识别到的缺陷。
由于题目要求实现一个基础版本,我们不会实现一个完整的编译器前端,而是采用一些简化的方法,比如正则表达式匹配,来模拟这个过程。
Java 实现
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class StaticCodeScanner {
public static List<String> scanCode(String code) {
List<String> defects = new ArrayList<>();
// 空指针访问
String nullAccessPattern = "\\b[a-zA-Z_][a-zA-Z0-9_]*\\s*=\\s*null\\s*;.*\\b\\1\\b\\.";
if (Pattern.matches(".*" + nullAccessPattern + ".*", code)) {
defects.add("Potential null pointer access");
}
// 数组越界访问
String arrayOutOfBoundsPattern = "\\b[a-zA-Z_][a-zA-Z0-9_]*\\s*\\[\\s*[0-9]+\\s*\\]\\s*;.*\\b\\1\\s*\\[\\s*[^0-9a-zA-Z_\\s]*\\s*\\]\\s*;";
if (Pattern.matches(".*" + arrayOutOfBoundsPattern + ".*", code)) {
defects.add("Potential array out of bounds access");
}
// 未处理的异常
String unhandledExceptionPattern = "\\btry\\b.*\\bcatch\\b.*";
if (!Pattern.compile(unhandledExceptionPattern).matcher(code).find()) {
defects.add("Potential unhandled exception");
}
// 不必要的对象创建
String unnecessaryObjectCreationPattern = "\\bnew\\b\\s+[a-zA-Z_][a-zA-Z0-9_]*\\s*\\(\\s*\\)\\s*;";
Matcher matcher = Pattern.compile(unnecessaryObjectCreationPattern).matcher(code);
while (matcher.find()) {
String objectName = matcher.group().split("\\s+")[1].replaceAll("\\(\\)", "");
if (!Pattern.compile("\\b" + objectName + "\\b\\s*=\\s*new\\b.*").matcher(code).find()) {
defects.add("Unnecessary object creation: " + objectName);
break; // 简化处理,只报告一个
}
}
return defects;
}
public static void main(String[] args) {
String code = "String str = null; str.length();\n" +
"int[] arr = new int[5]; arr[10] = 1;\n" +
"try { int x = 1 / 0; } finally { System.out.println(\"Finally\"); }\n" +
"new String();";
List<String> defects = scanCode(code);
for (String defect : defects) {
System.out.println(defect);
}
}
}
C++ 实现
#include <iostream>
#include <regex>
#include <vector>
#include <string>
std::vector<std::string> scanCode(const std::string& code) {
std::vector<std::string> defects;
// 空指针访问
std::regex nullAccessPattern(R"(\b[a-zA-Z_][a-zA-Z0-9_]*\s*=\s*null\s*;.*\b\1\b\.)");
if (std::regex_search(code, nullAccessPattern)) {
defects.push_back("Potential null pointer access");
}
// 数组越界访问
std::regex arrayOutOfBoundsPattern(R"(\b[a-zA-Z_][a-zA-Z0-9_]*\s*\[\s*[0-9]+\s*\]\s*;.*\b\1\s*\[\s*[^0-9a-zA-Z_\s]*\s*\]\s*;)");
if (std::regex_search(code, arrayOutOfBoundsPattern)) {
defects.push_back("Potential array out of bounds access");
}
// 未处理的异常
std::regex unhandledExceptionPattern(R"(\btry\b.*\bcatch\b.*)");
if (!std::regex_search(code, unhandledExceptionPattern)) {
defects.push_back("Potential unhandled exception");
}
// 不必要的对象创建
std::regex unnecessaryObjectCreationPattern(R"(\bnew\b\s+[a-zA-Z_][a-zA-Z0-9_]*\s*\(\s*\)\s*;)");
std::smatch match;
while (std::regex_search(code, match, unnecessaryObjectCreationPattern)) {
std::string objectName = match[0].substr(match[0].find_last_of(" ") + 1);
objectName = objectName.substr(0, objectName.find_first_of("("));
std::regex objectUsePattern(R"(\b" + objectName + R"\b\s*=\s*new\b.*)");
if (!std::regex_search(code, objectUsePattern)) {
defects.push_back("Unnecessary object creation: " + objectName);
break; // 简化处理,只报告一个
}
}
return defects;
}
int main() {
std::string code = "String str = null; str.length();\n"
"int arr[5]; arr[10] = 1;\n"
"try { int x = 1 / 0; } catch (...) {} finally { std::cout << \"Finally\"; }\n"
"new String();";
std::vector<std::string> defects = scanCode(code);
for (const auto& defect : defects) {
std::cout << defect << std::endl;
}
return 0;
}
Python 实现
import re
def scan_code(code):
defects = []
# 空指针访问
null_access_pattern = r'\b[a-zA-Z_][a-zA-Z0-9_]*\s*=\s*null\s*;.*\b\1\b\.'
if re.search(null_access_pattern, code):
defects.append("Potential null pointer access")
# 数组越界访问
array_out_of_bounds_pattern = r'\b[a-zA-Z_][a-zA-Z0-9_]*\s*\[\s*[0-9]+\s*\]\s*;.*\b\1\s*\[\s*[^0-9a-zA-Z_\s]*\s*\]\s*;'
if re.search(array_out_of_bounds_pattern, code):
defects.append("Potential array out of bounds access")
# 未处理的异常
unhandled_exception_pattern = r'\btry\b.*\bcatch\b.*'
if not re.search(unhandled_exception_pattern, code):
defects.append("Potential unhandled exception")
# 不必要的对象创建
unnecessary_object_creation_pattern = r'\bnew\b\s+[a-zA-Z_][a-zA-Z0-9_]*\s*\(\s*\)\s*;'
for match in re.finditer(unnecessary_object_creation_pattern, code):
object_name = match.group().split()[1].replace('()', '')
object_use_pattern = fr'\b{object_name}\b\s*=\s*new\b.*'
if not re.search(object_use