ソフトウェアエンジニア現役続行

雑多なことを綴ります

gcovを使ってテストカバー率を測定する

gcovというツールを使ってC言語のテストカバー率を測定することができます。gcovはgccパッケージに同梱されています。

たとえば次のようにHoge.cをtestHoge.cでテストするとき↓


[Oswald@fedora14 tmp]$ cat Hoge.c
int plus1(int i)
{
return i+1;
}

int minus2(int i)
{
return i-2;
}


[Oswald@fedora14 tmp]$ cat Hoge.h
int plus1(int i);
int minus2(int i);


[Oswald@fedora14 tmp]$ cat testHoge.c
#include "Hoge.h"
#include
#include

int main(void)
{
assert(11 == plus1(10));
printf("Test Finished!\n");
return 0;
}

コンパイルオプションに-fprofile-arcs -ftest-coverageをつけて、gcovをリンクしてコンパイルします↓


[Oswald@fedora14 tmp]$ gcc -fprofile-arcs -ftest-coverage -lgcov -o testHoge Hoge.c testHoge.c

コンパイルしたテストプログラムを実行します↓


[Oswald@fedora14 tmp]$ ./testHoge
Test Finished!

gcovコマンドで、テストされたクラスを指定すると、「テスト対象のコードは4行で、そのうち50%がテストされた」と出力されます↓


[Oswald@fedora14 tmp]$ gcov Hoge
File 'Hoge.c'
Lines executed:50.00% of 4
Hoge.c:creating 'Hoge.c.gcov'

また、Hoge.c.gconvというファイルが作成されていて、ここでテストされたところ・されていないところが分かります↓


[Oswald@fedora14 tmp]$ cat Hoge.c.gcov
-: 0:Source:Hoge.c
-: 0:Programs:2
1: 1:int plus1(int i)
-: 2:{
1: 3: return i+1;
-: 4:}
-: 5:
#####: 6:int minus2(int i)
-: 7:{
#####: 8: return i-2;
-: 9:}

「#####」の部分がテストされていないところです。

単純にCPUが実行した行に印がついていくようですね。なので、どんなテストフレームワークでも、この方法でカバー率を算出することができそうです。

DBD::SQLite-1.14に関数が戻ってこない不具合がある

Unix環境でperlのDBD::SQLite-1.14の関数を使ってsqlite3につなぐと、関数から戻ってこない不具合が起こることがあります。DBD::SQLite 1.14はCent OS 5.1に標準で入っているバージョンです。

再現プログラムは↓


use DBI;
DBI->connect('dbi:SQLite:dbname=/tmp/foo.sqlite', "", "");

このプログラムをulimit -vで仮想メモリを制限しながら実行します。すると、ある仮想メモリの大きさで実行すると、DBI->connect()から戻ってこないことがあります。その仮想メモリの大きさは、実行する環境によって変わります。

straceでシステムコールを追ったり、DBD::SQLite-1.14のソースコードを読み進めていって、DBD::SQLite-1.14のos_unix.cの中でpthread_create()に失敗したときのエラーハンドリングをしていないことに問題があることが分かりました。

os_unix.cの520行目のあたり↓


pthread_create(&t[0], 0, threadLockingTest, &d[0]);
pthread_create(&t[1], 0, threadLockingTest, &d[1]);
pthread_join(t[0], 0);
pthread_join(t[1], 0);

pthread_create()に失敗してもpthread_join()が呼ばれるため、t[0]のメモリの値によっては、ここでfutexロックがかかったまま固まってしまいます。

修正patchを提供しようと思いましたが、2011年01月15日の時点でのDBD::SQLiteの最新バージョンは1.31であり、このバージョンでは実装が大きく変更されていて、pthread_create()も呼ばれていないため、本家にpatchを提供するわけにもいかず。。。

簡単にこの不具合を解消するには、例えば以下のようにします。これでpthread_create()に失敗したときに固まらずにエラー終了してくれます。


int rc;
rc = pthread_create(&t[0], 0, threadLockingTest, &d[0]); assert(rc == 0);
rc = pthread_create(&t[1], 0, threadLockingTest, &d[1]); assert(rc == 0);
pthread_join(t[0], 0);
pthread_join(t[1], 0);

英語学習最強プログラム

シリコンバレーに行ってきた(2010年12月30日)のエントリで書いたのですが、海外で働くことにとても興味を持っています。転職するにしろ、留学するにしろ、今の会社で海外に転勤するにしろ、チャンスをつかむためには英語が出来なくてはならないと感じ、英語の勉強を始めることにしました。今までは専門書を読むことの一辺倒だったのですが、英語も並行して勉強していきます。

勉強法は、Amazonでたまたま見つけた中上級者がぶつかる壁を破る英語学習最強プログラムがとても良くて、これのとおりに勉強を進めています。5年前にTOEIC780点あったので、今から勉強を始めて、5月29日のTOEICで900点取得を目指します。

この本の良いところは中上級者向けの英語の本であること。初心者向けの英語学習法の本はたくさんあるんですが、中上級者向けの英語ってあまり見ないですよね。

また、この本は勉強法をとても具体的・効率的に指南しています。例えば英語の勉強法として「英単語を覚えなさい」と書かれている本は多く、それ自体は正しいのですが、具体的な英単語の覚え方を説いている本は少ないと思います。「多読しろ」とか「時間をいっぱい使え」などのような根性論が多いように思います。この本では、どうやったら効率的に英単語が覚えられるかがとても具体的に書かれています。

本のタイトルのとおりですが、中上級者で壁にぶつかっている人にはオススメだと思います。初中級者には、〈具体的・効率的〉英語学習最強プログラムがオススメです。こちらも読みましたが、とても具体的で良い本でした。

iPod touchでpodcastを直接ダウンロードする方法

今までは、PCでiTunesを立ち上げて、podcastをダウンロードしてからiPod touchに転送していました。

PCが手元にないときに、Wifi環境のおいてiPod touchで直接ダウンロードしようとしたら、やり方がすぐに分からなくて迷ったので、メモしておきます。

1. iPod touchpodcastで「さらにエピソードを入手」を押す

f:id:Oswald:20110103100715p:image

2. 新しいpodcastをリストされるので「無料」を押す

f:id:Oswald:20110103100648p:image

3. 「無料」が「ダウンロード」に変わるので、これを押す

f:id:Oswald:20110103100716p:image

シリコンバレーに行ってきた

年末の休暇を使って、アメリカのカリフォルニア州に旅行してきました。サンフランシスコを観光したり、ヨセミテ国立公園でのんびりしたり。

そんな中で、一番、印象に残っているのは、シリコンバレーを訪れ、そこにある半導体企業で働いている知り合いと、話をすることができたことです。

彼はもともと僕と同じ会社で働いていたのですが、アメリカ駐在を経て、シリコンバレーの半導体企業に転職しています。アメリカ永住を決めた一番の理由は家族だと言っていました。日本にいたときは毎晩深夜まで仕事をしていたが、アメリカに来てからは平日に家族と夕ご飯が食べられるようになったと言っていました。働き方にゆとりを感じます。

街の雰囲気からもゆとりを感じます。家は広く、庭も大きい。道路が広くて渋滞も少なく、ここにいると大らかな気持ちになります。日本でせせこましく働いている自分が悲しくなってきます。

アメリカにある選択肢の豊富さにもゆとりというか自由を感じます。例えば、アメリカでは大学生の年齢層がとても幅広いそうです。というのもアメリカには定年という概念がなく、何歳まででも働き続けられます。だから、何歳であろうと自分のキャリアアップやキャリア転換のために自由に大学に入り直すそうです。

また、よく聞く話ではありますが、やはりアメリカの大学生は日本に比べて、とてもよく勉強するそうです。驚いたのは、アメリカの企業には「新卒採用」という概念がないということ。転職が盛んなアメリカで、大学生は中途採用の人たちと同じ土俵で仕事を探さなくてはいけません。だから、アメリカの大学生は必死で勉強して、インターンシップで就業体験や人脈を得て、内定を勝ち取るのだそうです。

就職できれば安泰というわけではなく、アメリカ企業はドラスティックに従業員のクビを切ります。例えば、企業が着手している事業から撤退を決めたら、その事業部門のメンバーがみんなクビになってしまうようなことも当然のように起きる。彼自身もそれを経験したそうです。アメリカで働くということは、そういうリスクも覚悟して働かなくてはならないと話していました。

他にもいろいろ話を聞きました。こういった話はインターネットから得られるかも知れませんが、実際にその場に行き、そこで働く人から話を聞くと、感じ方が全然違います。

日本と比較して、アメリカで働くことの長所も短所もたくさんあると思います。これから続く長い人生を考えると、一度は違う国で働いてみたいなと思うようになりました。違う文化や価値観に触れられることは自分の人生にきっとプラスになると思います。

貴重な年末の休日を費やして、車であちこち案内してくれて、話をしてくれた彼には感謝の気持ちでいっぱいです。

案内してくれた場所の一つ。シリコンバレー発祥の地と言われるHP創業のガレージです。クリスマスシーズンだったので、リースが架かっていて可愛いですね。
f:id:Oswald:20101230224203j:image

fflushとfsyncとfdatasync

どれもバッファリングされているデータをフラッシュする関数ですが、それぞれの違いを再確認しました。

int fflush(FILE *stream);
Cライブラリが与えているユーザー空間のバッファしかフラッシュしない。データが物理的にディスクに保存されることを保証したければ、fsync(2)などでカーネルバッファもフラッシュしなければならない。

int fsync(int fd);
fdで参照されているファイルのキャッシュ(カーネル内のバッファ)をディスクデバイスにフラッシュする。この呼び出しはフラッシュが終わったとデバイスが報告するまでブロックする。

int fdatasync(int fd);
fsync()と同様だが、fdatasync()は、それ以降のデータ読み込みを正しく扱うためにメタデータ(たとえばst_atime や st_mtime)が必要にならない限り、変更されたメタデータをフラッシュしない。fdatasync()の狙いは、全てのメタデータをディスクと同期する必要のないアプリケーションに対して、ディスクアクセスを減らすことである


これらを踏まえると、Cライブラリ(fputsなど)を使って書き込んだデータを効率的かつ確実にディスクに保存するには、fflush(3)を呼んで、かつfdatasync(2)を呼ぶのが良さそうです。

以下がサンプルソースです。エラー処理は省いています。


/* 第1引数で与えられたファイルに、
* 第2引数で与えられた文字を書き込むプログラム */
int main(int argc, char **argv)
{
FILE *writer = fopen(argv[1], "w");
int fd = fileno(writer);

// データを書き込み
fputs(argv[2], writer);
fputc('\n', writer);

// Cライブラリが与えているユーザー空間のバッファをフラッシュ
fflush(writer);

// fdで参照しているファイルのキャッシュをディスクにフラッシュ
fdatasync(fd);

// fcloseでファイルをクローズ。close(fd)まで呼ぶ必要はない
fclose(writer);

return 0;
}

「はじめて読む486」が素晴らしい

Linuxカーネル2.6解読室を読み進めているのですが、割り込みやメモリ管理(仮想記憶、ページングなど)など、OSに関するある程度の前提知識が必要で、読んでて理解できないところも少なくありませんでした。

仮想記憶、ページングなどは、Windowsはなぜ動くのかでも一通り読みましたが、よく理解できず、自分の理解力が足りないのだと諦めていました。

ところが、いま読んでいるはじめて読む486—32ビットコンピュータをやさしく語るだと、今の32ビットOSの基礎知識がとても分かりやすく説明されていて、理解することができました。図やたとえ話を使った説明が絶妙!とても分かりやすかったです。
この本は1994年から出版されていたんですね。LinuxのおかげでOSが身近になってきているいま、この本の価値が再認識されてくるのではないでしょうか。OSを理解したい人は、この本を読むと良いと思います。

はじめて読む486—32ビットコンピュータをやさしく語るも、まったく知識がない状態では難しいと思います。そのときは入門編として、はじめて読む8086—16ビット・コンピュータをやさしく語る図解雑学 CPUの働きと高速化のしくみを読むが良いと思います。どちらも容易に素早く読み終えることができます。