最有效方法是用正则表达式批量扫描三类取余错误:①除数为0(匹配[/ %]\s0\b);②负数参与取余(如%\s-\w+、-\w+\s*%);③整型溢出(如% -1、% INT_MIN等),并辅以编译器警告和UBSan验证。

直接用正则表达式批量扫描最有效,重点盯住除数为0、负数参与运算、以及整型溢出这三类典型错误。
找除数为0的%操作
这是最危险的写法,运行时直接崩溃。匹配模式很简单:
%\s*0\b注意要加单词边界 \b,避免把 10、0x0 之类误伤。实际扫描时建议同时检查 / 0 和 % 0,用同一正则:[/%]\s*0\b
找负数参与取余的地方
C/C++/Java里 a % b 的符号取决于被除数 a,但很多老代码默认结果非负,逻辑就错了。搜这两类:
- %\s*-\w+(右边是负变量或常量,如 % -n、% -10)
- -\w+\s*%(左边是负变量,如 -x % 5)
别漏掉宏定义里的负值,比如 %-MAX_LEN,可先预处理再扫,或加一条 %[^;{]*-[\d\w]+ 宽松匹配。
找可能溢出的整型取余
比如 INT_MIN % -1 在C里是未定义行为。搜硬编码的极端值:
% (?:-?0x[0-9A-Fa-f]+|-?\d+)然后人工核对是否落在 INT_MIN、INT_MAX 附近。也可以用编译器警告辅助:开 -Wdiv-by-zero 和 -Woverflow,部分溢出情况会被捕获。
配套动作不能少
光靠正则不够,得结合上下文判断:
- 把匹配行连同前后3行一起导出,方便看变量类型和赋值来源
- 对疑似问题点,加临时断言,比如 assert(b != 0); assert(b != -1 || a != INT_MIN);
- 有单元测试的模块,跑一遍并开启 UBSan(UndefinedBehaviorSanitizer),它能当场报出非法取余

















