静的プログラム解析ツールの実力は? 100
ストーリー by nabeshin
プログラム洗濯機 部門より
プログラム洗濯機 部門より
あるAnonymous Coward 曰く、
組み込み系の開発では様々なベンダーが次世代静的プログラム解析ツールともいえる製品を開発し、世に送り出している(本家/.記事)。これらツールはNULLポインタ参照やバッファオーバーフローの脆弱性、競合状態やメモリリークなどを検知できるとされている。本家では、Linuxカーネルで使われているsparseのほか、FindBugsや、DoubleCheck、Identify critical defectsなどといったツールが話に出ている。
実際、次世代静的プログラム解析ツールを導入することで開発方法やテストサイクルに変化はあるのだろうか? 新しい解析ツールは既存のものよりそんなに実力が違うのだろうか? 諸氏のご意見を求む。
出てくる警告にどう対処するのかが問題 (スコア:5, すばらしい洞察)
# しかも、周りがヤイのヤイの言っても、今まで一度も直らなかったぐらい
# 上から下まで、ものを判っていない。
というわけで、このようなツールを使ったからどう、という事ではありません。
このようなツールの出力にどう対処するかが問題。また、このようなツールが
出してくる警告の量から、プログラム改善にかかる時間を正確に見積もる、などの
マネージメント能力も大事でしょう。
fjの教祖様
Re:出てくる警告にどう対処するのかが問題 (スコア:2, すばらしい洞察)
# みたいなー。
Re:出てくる警告にどう対処するのかが問題 (スコア:4, おもしろおかしい)
「わあ!見る見る消えていきますね!」
# 符号無し整数型の変数と負数のエラー定数を比較した、あの頃の記憶
Re:出てくる警告にどう対処するのかが問題 (スコア:3, おもしろおかしい)
警告が出た行を丸ごと削除するという荒技が・・・・
Re:出てくる警告にどう対処するのかが問題 (スコア:1, おもしろおかしい)
#「だってコンパイとおんないから」じゃねぇ
#仏の顔って何度までだっけ? orz
Re:出てくる警告にどう対処するのかが問題 (スコア:1)
だって、ほかからいろいろいじれた方が楽チンだっ、て思うんだもの。
ごめんなさい。ごめんなさい。
Re:出てくる警告にどう対処するのかが問題 (スコア:2, 興味深い)
そしてそういう人たちは、「何が問題なのか」をいくら説明しても馬耳東風なのです。
「で、どうすればいいって~~??!」
一瞬「この世から消えろ」と「プログラマ辞めろ」とどっちを先に言おうか悩んだのは秘密だ。
そして実際に言ったせりふは…
「… あぁ… どうやら天もあなたの今の発言には怒り狂ったようですね。
寝言は寝て言うように」
# fjの教祖様の怒りが頂点に達すると、雷が天から降り注ぐ…ときもあるのだ。
fjの教祖様
Re:出てくる警告にどう対処するのかが問題 (スコア:1)
いやいや普通なら、
「Warnningは全部消せ。」
「消せないなら、消せない理由を報告書を書いて出せ。」
って、いっておくだけで、
みんな必死にシンタックスな問題からセマンティックな問題に昇華してくれます。
書類、書くの嫌いだから。
セマンティックな問題は、コードレビューしか対処方法はないですよね?
コードレビューは、レビュアという教育者を育てるし、
プログラマ教育の教材そのものではないですか。
バグはでるものと割り切って、バグを多く出すレビュアを、
首にするなり、再教育するなり、調教するなり、
そこまできたらマネージャー自由にしてもいいですよね。
# という、牧歌的な時代はとうの昔に終わってましたか。そうでしたか。
Re:出てくる警告にどう対処するのかが問題 (スコア:1)
何せ向上心が皆無な状態では何を教えても無駄なんだから。
もっとも、その「何が問題なのか」には「半年後くらいの夜中に呼び出されてもう忘れちゃってるコードと格闘して、稀にしか再現しないバグを追う羽目になる...こともある」とか、メカものなら「暴走して人死にが出る...こともある」あたりまで含まれてないとわかってもらえないかもしれないけど。
Re:出てくる警告にどう対処するのかが問題 (スコア:1)
the.ACount
Re:出てくる警告にどう対処するのかが問題 (スコア:2, すばらしい洞察)
完成したコードにツールを通したあとで警告を減らすために修正するとけっこうひどいことになりますが、この手のツールに引っかからないようなコーディングスタイルを身に着けるというのはかなり有効ではないかと思います。
なので、製品のチェックに使用するなら、コーディング工程のかなり早い段階(クロスレビュー前)で使用し、既存のコードへの使用は傾向分析等を主にするのがいいんじゃないですかね。
これなら、逃げでごまかすよりも、警告の出にくいコードを書くようになると思うんですが。
しもべは投稿を求める →スッポン放送局がくいつく →バンブラの新作が発売される
使う側の人間は少数派ですか? (スコア:3, 興味深い)
静的解析ツールについては組み込み系の中の車両系では普通に用いられています。 使う理由としては
特に近年、静的解析ツールに注目が集まっているせいか、ET2007でのチュートリアルセッション( http://www.jasa.or.jp/et/ET2007/conference/info_ts.html#TS-6 [jasa.or.jp])でもアイシン精機の方が講演中で静的解析ツールの導入・活用方法について触れられています。
私の知っているメーカーでは、静的解析ツールが出力した警告の報告・確認事項・対処(対策)法をマニュアル化して徹底させています。 しかし、静的解析検査はインフルエンザのワクチンのようなもので、一部の不具合の混入を防止するための手段の一つでしかなく、すべての不具合を検出できるわけではありません。 でも、最後は必ず複数の人間でコードレビューを行います。
また、車両系では製品を欧州に輸出するためには、開発プロセス中でMISRA-Cを用いなければならないようなので、選択したルールを満たしているかどうかの自動チェックにも用いています。
ツールを利用するタイミングですが akiraani さんが述べられているように、短時間で解析結果が出せるツールを
していますし、ツールによっては統合開発環境(Eclipse/HEW等)に組み込めるので、コンパイルの前にチェックを必ず行わせるようにしています。また、検出率が高いが実行時間が長いツールも用いており、こちらは金曜日の夕方に解析を開始させると月曜日の朝のミーティングの前には結果が出ます。 そのため月曜日は検出された問題点に対する対処などを話し合っています。
ほかに、静的解析の他にもデッドロック発生の可能性やタイミングの正しさを確認するための動的解析環境の利用もマニュアルで指示されており、開発プロセス中でツールを用いるのが当たり前になっています。
----(中に近い人なので話せる範囲で。)
Re:出てくる警告にどう対処するのかが問題 (スコア:1, 興味深い)
中でも最凶最悪なのは、関数の途中での return 禁止というものです。
枝刈りして関数を抜けたいのに、フラグを引き回して入れ子が深くなって読みづらいのです。
なにが嬉しくて可読性を落とすのか。教えて!エロイひと!
Re:出てくる警告にどう対処するのかが問題 (スコア:3, 興味深い)
int func()
{
lock();
...
if (statement_stands)
{
/* ここでロックをはずすのを忘れる */
return;
}
...
unlock();
return
}
とか.
Re:出てくる警告にどう対処するのかが問題 (スコア:1)
Re:出てくる警告にどう対処するのかが問題 (スコア:1, 参考になる)
Re:出てくる警告にどう対処するのかが問題 (スコア:1)
ロック対象が増えた段階で、プログラム上、無理がなければ、すぐに関数を分けてしまう方なので、あまり気にならないなぁ。
lock1();
...
lock2();
...
unlock1();
...
unlock2();
のような場合は1つで書かざる得ないが。
(でも、こういう例では、途中から抜けるような処理はご法度かなぁ。)
Re:出てくる警告にどう対処するのかが問題 (スコア:1)
Re:そして、重箱の隅(Re:出てくる警告にどう対処するのかが問題) (スコア:1)
Re:出てくる警告にどう対処するのかが問題 (スコア:1)
struct DoUndoLock {
DoUndoLock() { lock(); }
~DoUndoLock() {unlock(); }
}
void func()
{
DoUndoLock locker;
...
if (statement) {
...
return;
}
...
return;
}
みたいな.
Re:出てくる警告にどう対処するのかが問題 (スコア:2, 興味深い)
MISRA-Cってのは自分で適切なルールを選んで適用するものです。
ですから、関数途中のreturnを禁止するとうまくない理由をちゃんと説明して
そのルールを外してもらうのがMISRA-Cのやり方です。
外してもらえないのなら、あなたの説明が悪いか、ボスand/or顧客がアレなのか、どちらかあるいは両方です。
MISRA-Cは正しいのですw
Re:出てくる警告にどう対処するのかが問題 (スコア:1)
メモリリークやハンドルリークなんかは場所の特定がたいへんに面倒なので、コーディングレビューで出来るだけ潰しておきたいというのは考え方としてはありだと思うけど。
クラス使ってるとデストラクタでカバーできるんでかまわないんでしょうけど、組み込みではそうもいきませんし。
しもべは投稿を求める →スッポン放送局がくいつく →バンブラの新作が発売される
Re:出てくる警告にどう対処するのかが問題 (スコア:1, 興味深い)
#最初に見たとき意味わかんなくて「このループ必要ないよね」と思ってがしがし書き換えてました。
そういや先日も (スコア:1)
署名スパムがウザい?アカウント作って非表示に設定すればスッキリさ。
Re: (スコア:0)
>このようなツールの出力にどう対処するかが問題。
「素晴らしい洞察」ですな。
Eclipseなんかのツールを使う人の中には酷いコードを書く人も少なくないけれど、
新人に適切な対処の仕方を教えるためには、Emacsみたいな単純なエディタを使った
方が教育効果が高いのかも。
Re: (スコア:0)
プログラム力とは違うが、自分に合ったツールを見繕う力も必要だと思う。
Re: (スコア:0)
Re:出てくる警告にどう対処するのかが問題 (スコア:2, すばらしい洞察)
.
年をとってもコーディングを続けられる(続けざるを得ない、ではなくね)人たちの多くは「最初の頃からずっと使い続けられているエディタ」である Emacs や vi を使っている人が多いと思います。
# 私も Final を一時期使っていたが、結局それらは生き残らなかった…
一方で、若い人たちの多くは Eclipse を使っているでしょう。
と言うことは、単純に考えても Eclipse 側には「若手が多い」というバイアスがかかります。
プログラミングもやはり経験値がある程度ものを言いますので、「若手が多い」環境はどうしても品質が下がる、という傾向が出てしまいます。
コーディングを「できなくなる」人たちと言うのは、レベルが低い側ほど脱落率が高いでしょう。と言うことは、同じ世代のプログラマは年齢が上がるほど、平均レベルが高くなるはずです。
.
と言うわけで、20年ほど前に「vi/Emacsなんか使っている奴らのコードは使い物にならん」と言われたのと同じ意味において、今の Eclipse 使いのコードは醜い側に広く分布していると思われます。あと20年もすれば Eclipse よりも便利なツールが現れて新人はみなそちらを使うようになり、きっと言うようになるでしょう。
『xxxx を使っている奴らのコードは醜くていかん』
fjの教祖様
Re:出てくる警告にどう対処するのかが問題 (スコア:2, すばらしい洞察)
>「最初の頃からずっと使い続けられているエディタ」である Emacs や vi を使っている人が多いと思います。
多くかどうかは知らないけど、Emacsを使ってる人はEclipse『も』使ってる人が結構いますよ。
Emacsを使い続けているのは「最初の頃から使っているから」「慣れているから」などという
理由ではなく、エディタとしてはEmacsの方が遙かに優れているからです。
#Eclipseは統合環境である以上はエディタが貧弱なのは当たり前。
より適切な道具を取捨選択して使った結果、今でもエディタにはEmacsを選択する。
それだけのことです。
>と言うことは、単純に考えても Eclipse 側には「若手が多い」というバイアスがかかります。
あまりに単純化しすぎでは。
上にも挙げたように、Emacsを使ってる人がEclipseも使っていることが多々あります。
Eclipseから入った若手でも、(おそらくごく一部ではあるが、)Emacsを使ってる人もいます。
#中にはずっとメモ帳でやってきて、最近になってやっとEclipseを覚えた
#『経験豊富な熟練者』もいるかもしれないけど、一緒にやってくのには不安を覚える。
Eclipseから入り、そしてそれ以外を知らない人の中には、自分では何も考えず、ツール
が出す指示に従って切り張りする人がいます。それでエラーは出なくなるし、コンパイルも
通ります。でもそれはプログラミングと呼ばれる作業とは全く異なるものでしょう。
エディタは(たとえそれがEmacsであっても)何も指示してくれないので、自分で考えない人、
考えられない人は最初の段階で躓きます。またそれを自分で自覚できます。何が分かって
ないのかに気付くことが、学習への第一歩です。
便利すぎる道具は、初心者が学習する時には逆効果になりかねません。
Re:出てくる警告にどう対処するのかが問題 (スコア:1, 興味深い)
そしてemacsもVSもマクロガリガリ使いますし、Eclipseに至っては独自のプラグインも作ります(それがマクロと同じ意味だから)
ここが肝心な点ですがキーバインドは全部Emacsなんです、要するにアタマで使う部分(機能)と体が覚えた部分(キーバインド)ってのは別の話なんです。(VSのキーバインドをemacsにするためにxemacsから全面的にマクロを使って割り当て直しにしたせいでVS2003,2005,2008と全部個別に対応する羽目になったけど)
#他人が自分のVSを使うとパニックになるように、僕がまっさらのVSを使うとプリンターダイアログが
Re:出てくる警告にどう対処するのかが問題 (スコア:1)
多数こそが全体の傾向を決めるのであって、「例外」が少々いても、全体の傾向には影響しない。
# Emacs が優秀である? 知ってるよそんなの。
# しかし、それでも Eclipse 使いの大半は Emacs 使い「ではない」のだよ。
fjの教祖様
Re:出てくる警告にどう対処するのかが問題 (スコア:1)
fjの教祖様
Re: (スコア:0)
今、そのシステムはインフラの一部としてまだ稼動しているようです。
# さすがにAC。
Re:出てくる警告にどう対処するのかが問題 (スコア:1, おもしろおかしい)
Re:出てくる警告にどう対処するのかが問題 (スコア:1, すばらしい洞察)
少なくとも「美しくない」=「間違い」ではありません。
顧客の「デーモンがcoreを吐く」という要望に対しては
- 美しいが高コストな方法: デバッグ、ソースコードの修正を行い、coreを吐かないようにする
- 美しくないが低コストな方法: coreを吐いても、coreファイルを保存しないようにする
という感じで、複数の選択肢があります。
ここで後者の低コストな方法で顧客が満足してくれるのなら、何も問題はないと思います。
# 本来は、ちゃんと顧客に複数の選択肢があることを説明した上で、どちらか一方を提案するべきですが。
Re:出てくる警告にどう対処するのかが問題 (スコア:1)
これはあちらこちらで何度も聞くが、じゃぁ「間違っていないコード」を見るとたいてい「美しい」。
醜いコードが醜くなるのは、例外の固まりになるから。そして例外だらけのロジックは大抵煩雑で(複雑ではなく煩雑で)、人間の誤りを誘発する。しかも例外ケースは滅多に走らないため、『動いているシステム』であってもバグを内包したままである確率はきわめて高い。
もちろん、そのようなコードが「あとどれぐらい使われるのか」によっては、直すコストより放置して問題が起こったときに対処するコストの方が安い(期待値として)と判断されるかもしれない。しかし、それは「障害対策コスト」と「障害発生確率」から算出されるべきであって、
『醜くても動いているんだからいいじゃん。直すのにコストかかるし』
は、さすがによくない。
fjの教祖様
Re: (スコア:0)
・処理に失敗するのはかまわないが、ディスク容量を食うのは困るらしい
という条件の下で似たような対処をやったことはある。
#開発部に上げても「要求仕様に沿ってない状況での不具合には対応する必要はない」という
#回答しか返ってこないし。
Re:いまだにC/C++を使っているのが問題 (スコア:2, すばらしい洞察)
C/C++が採用される(活かされる)のだと思いますが。
問題と思うなら何が問題で、言語にどのような仕様があれば解決するのか
説明して頂けないでしょうか。
#こういうことを尋ねると大概ライブラリの問題など言語に関係ない方向に進む。
Re:いまだにC/C++を使っているのが問題 (スコア:4, おもしろおかしい)
Re:いまだにC/C++を使っているのが問題 (スコア:1)
Re:諦めの境地 (スコア:1)
そこそこ出来る人による使用例を求む (スコア:2, すばらしい洞察)
「ダメダメな人にでも使わせるとダメダメなプログラムがそれなりの出来になるツール」ではなくて、
「それなりの人に使わせることでそれなりなプログラムがなかなか良い出来になるツール」なのでしょう。
「すごい人に使わせてもすごいプログラムが完璧なできになるツール」でもないと思います。むしろこの場合は、ツールの出来によっては「見当はずれな警告しか出ないでストレスの元にしかならないツール」であるかもしれません。
「こーんなヤツにこんなツールを使わせても役には立たないよ!」という話ばかりでなく、
こちらの話も聞きたいのですが。「甲のツールを使っていたらこんな警告が出て、こんなバグを見つけたよー」とかいう話もよろしく。
Re:そこそこ出来る人による使用例を求む (スコア:2, 参考になる)
ごくまれに、なんで警告が出るんだ出るわけないだろってこともあります。
警告の内容は例えば
1.int型に対しビット演算を行うと「整数型に対してビット演算を行っています」ってな感じの警告が出ます。
この場合unsigned int型でビット演算を行えば警告は出ません。
2.もしchar型の範囲が-127~128だった場合
0xffを代入しようとした場合これも警告が出ます。
型の範囲外の値を代入しようとしているためです。
charの範囲は環境により異なるためなんともいえませんが。
3.short型(16ビット)にint型(32ビット)の変数を代入させた場合「暗黙のキャストが行われます」とか出ます。
この場合、short型にキャストするれば警告が消えます。short型の変数に入れて良いかもチェック巣r必要も出てきます。
ただ、int型(32ビット)にshort型(16ビット)の変数を代入した場合は警告は出ません。
(ほかのツールなら警告が出るかもしれませんが)
4.unsigned int型のiに対し
for(i=100;i>=0;i--)
なんて書いた場合も警告が出ますね。「for文の条件は常に真です。」といった内容だったかと。
5. int data;
char tmp = 5;
data = tmp << 16;
これも警告が出ます。警告の文面は忘れましたが
tmpの型の範囲外へシフトを行っており情報が失われる。だったかな?
tmpは最大8(7?)ビットしかシフトできないためです。
この場合
data = ((int)tmp) << 16;
とすればよかったと思います。
6. #define AAA(data,val) val = data
これも警告が出ます。
#define AAA(data,val) (val) = (data)
とする必要があります。
7. #define BBB(data1,data2,val) \
{ \
(data1)=(val); \
(data2)=(val); \
}
この警告は「valは2度以上使用されます」といった内容だったかと。
BBB(a,b,c++);
と書いた場合cが意図していない内容になるかもしれないためだと思います。
もっと深い警告もありますが今手元にデータが無いので内容覚えてません。
かなりうろ覚えなため間違ってるかもしれません。
そもそも「こんなコード書くなよ」といわれればそれまでですが。
Re:そこそこ出来る人による使用例を求む (スコア:1, 参考になる)
いや、うろ覚えの内容を列挙しただけですので。。。
あ、ここ間違ってたのか。と気づかせてくれたのでそう思い込んでるだけかな。
>「freeし忘れのパスがあります」とか指摘してくれる
残念ながら指摘してくれません。
例えば
char *get_data_area(int size) {
char *tmp;
tmp = (char *)malloc (size);
return(tmp);
}
なんてコードが有った場合は?
静的解析はプログラムの内容を理解してくれません。
そのためmallocしっぱなしでfreeしていない事や
スレッド、資源の排他制御などは考慮しません。
あくまでも構文におかしな点があるかどうかをチェックしているだけですね。
うっかり間違ったものを見つけてくれるツールという風に捕らえればいいかと思います。
1. if(data||DATA_FLAG1){}
ビット演算のつもりがorだった場合警告してくれます。
2. if(a==0||b==d+1|c==func()){}
これは
・2項演算子が複数あるため()をつけるべき
・||、&&に副作用があります
・内容は忘れましたが2つ目と3つ目の条件式が|になってる
と警告したような気がします。
if((a==0)||(b==(d+1))||(c==func())){}
と修正。
3. int func ( DATA* data ) {
int a = 0;
a = data->b;
}
これはNULLの可能性があるポインタを間接参照しているという警告がでますね。
関数の最初にNULLチェックすべきです。
呼び出し元でNULLチェックしていたとしても警告は出たと思います。
あとaの初期値は無意味だとか。スタックの無駄遣い。
配列の範囲外を指定する可能性がある場合も警告が出ますね。
コーディング上範囲内に収まってる「はず」だったのが
実は範囲外を指定するかもしれない事を指摘したり。
境界調整のポインタは危ないとか。
>アセンブラ経験があればそれほど不思議な警告ではないような。
まぁそうですね。
freeし忘れとかのプログラムの内容を理解してくれる解析ツールなんてあるんだろうか。
あったら教えてください。
Re:そこそこ出来る人による使用例を求む (スコア:1)
こいつ、最初に使ったとき、コードレビューで見逃していてテストでも検出できなかったヌルポな可能性をサックり出してくれて感心しました。
また、表現の揺らぎなんかも検出してくれるのがうれしいですね。 また、JDBCを使って直接DBを叩いているなら、文字列結合でSQLを作成している部分を探してくれたり、servletにフィールドを作っているコードを検出したりと、自分のミスだけでなく他のメンバーのコード管理にも有効に使える代物ではないかと思います。
Javaで開発をしているなら使わない手はないと思うのですが、周囲ではなぜか少数派です…。
弱点があるとするなら、項目の有効無効設定の単位が少し大雑把なもんで、適用除外をする場面が出てきてしまって少々面倒なルール記述をしなきゃいけなくなる場合があるってところくらいだと思います。
Re:そこそこ出来る人による使用例を求む (スコア:1)
すごい!
cos()関数の決定性/非決定性までチェックしてくれるのですね?
そんなわけないでしょ。
標準関数だけやってくれるのかな?
# 複雑なコードを喰わせたら、コンパイラと違う結果を出しそうで怖いですね。
なんといわれようと (スコア:0)
Re:doxygen(古い? (スコア:2, おもしろおかしい)
Re:doxygen(古い? (スコア:1)
Re:doxygen(古い? (スコア:1)
$ ctags *.c