2019.Nov.03
よしだ たけひこ
職業 : 組込みシステム技術者
産業用プリンターのファームウェアを
C言語 や C++ で開発しています。
などなど
const修飾 (定数宣言) を途中で外す悪弊が蔓延
const char the_parameters[][] = {
{ 0x00, 0x80, 0x00, 0xff, /* 中略 */ },
{ 0x00, 0x8f, 0x00, 0xf0, /* 中略 */ },
/* 中略 */,
};
void foo (void) {
/* 中略 */
ret = bar( (char*) the_parameters[i] );
/* 中略 */
}
int bar (char* parameters) {
/* 中略 */
}
(だったら定数のままで渡せばいいのに…)
constだったポインタ参照先を書き換え!
#!/usr/bin/env ruby
begin
target_files = Dir.glob("src/**/*.c") + Dir.glob("src/**/*.h")
target_files.each do |file_name|
File.open(file_name) do |f|
count = 0
f.each_line do |line|
begin
line.encode!("UTF-8", "CP932")
if line.match(/^(static\s+)*const\s+/) then
count = count + 1
end
rescue => e
end
end
puts "#{file_name},#{count}" if count > 0
end
end
end
target_files
= Dir.glob("src/**/*.c") + Dir.glob("src/**/*.h")
line.encode!("UTF-8", "CP932")
line.match(/^(static\s+)*const\s+/)
$ ruby const_counter.rb
src/object.c, 1
src/class.c, 1
src/array.c, 1
src/string.c, 6
src/fmt_fp.c, 1
src/backtrace.c, 1
src/symbol.c, 4
src/proc.c, 1
【註】 mruby のソースコードを例にしています
static const mrb_code each_iseq[] = {
OP_ENTER, 0x0, 0x00, 0x1, /* OP_ENTER 0:0:0:0:0:0:1 */
OP_JMPIF, 0x1, 0x0, 19, /* OP_JMPIF R1 19 */
OP_LOADSELF, 0x3, /* OP_LOADSELF R3 */
OP_LOADSYM, 0x4, 0x0, /* OP_LOADSYM R4 :each*/
/* 中略 */
};
static const char *
char_adjust(const char *beg, const char *end, const char *ptr)
{
if ((ptr > beg || ptr < end) && (*ptr & 0xc0) == 0x80) {
const int utf8_adjust_max = 3;
/* 中略 */
}
項目 | 計測値 |
---|---|
計測対象コード規模 | 約 1,200 ファイル 約 400 KLOC |
Rubyスクリプトヒット | 約 300 ファイル 約 5,000 件 |
不適切なconst外し | 約 500 件 |
不正な定数の書換え | 9 件 |