2012年8月31日金曜日

Jenkins の安定バージョンっていくつ?

これを書いている時点で Jenkins の最新バージョンは 1.479 。
会社で使っている Jenkins のバージョンは 1.472 。

今使っているバージョンで大きな不満はないものの、どことなく不安定な気がしています。
履歴(change log)を見ればどんな修正があったか分かりますし、issue 見れば不具合情報も見れます。

ただ、パッと見てどのバージョンが安定していて、どのバージョンが不安定なのか全然わからない


自宅で使っている Jenkins は最新バージョンを追っかけてますが、1週間に1回起動するかどうかです。
会社と違ってスレーブを使ってないので、安定しているかどうかの判断がしにくいのです。



というわけで、どこかに安定(or おすすめの)バージョンの情報ないですかね?

2012年8月28日火曜日

タブレットを買った

先日、携帯を変えることになりドコモショップに行ってきました。
目的の携帯を手に入れることは出来たのですが、
店員さんの口車にまんまとハマりタブレットも買ってしまいました。

デメリットもあまりないしと買ったものの、毎月の出費が増えたのも事実・・・
無駄にしないように活用しないとなぁ

ってのをタブレットで書いて満足しているのであった。

2012年8月22日水曜日

strcpy_s が失敗したとき

今回は、「CRTセキュリティ強化」のことについてです。

早速本題です。
strcpy_s を使っている人がどれだけいるかわかりませんが、少なくはないと思います。
私もそのひとりです。
今回は、この strcpy_s が失敗したときについてです。

失敗したときの挙動
strcpy_s 関数ですが、第二引数に「コピー先の文字列バッファのサイズ」を指定すると思います。
指定サイズを超えてコピーが行われた場合、戻り値にエラー値が返ってきます。

と、思っていたのですが実際の挙動は少し違っていました。

MSDN より引用
strDestination または strSource が null ポインタの場合、またはコピー先文字列が小さすぎる場合は、「パラメータの検証」に説明されているように、無効なパラメータ ハンドラが呼び出されます。実行の継続が許可された場合、これらの関数は EINVAL を返し、errno を EINVAL に設定します。

どうやら、「無効なパラメータ ハンドラ」というものが呼ばれるようです。

試してみた
ということで、以下のコードで試してみました。

#include <gtest/gtest.h>

int main(int, char**)
{
    const char a[] ="test";
    char b[2];
    ASSERT_EQ(0, strcpy_s(b, a));
    return 0;
}

デバッグビルドで実行すると


で、中止 or 無視 を選択するとプログラムが終了。


リリースビルドの場合、


このように WerFault.exe が実行される。
「プログラムを終了します」を選択すると文字通りプログラムが終了します。
この点が少し問題で、この時失敗も返さず、例外も投げず終了していくので、
クラッシュレポートを出力するようなプログラムの場合、何もできずに終了してしまいます。

gtest の対応は?
上の検証コードが gtest のアサーションのみ利用しているのは理由があって、
gtest は上の挙動と異なるからです。

#include <gtest/gtest.h>

int main(int, char**)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
TEST(CRT, strcpy_s)
{
    const char a[] ="test";
    char b[2];
    ASSERT_EQ(0, strcpy_s(b, a));
}

このコードをリリースビルドで実行すると、

なにごともなく終了していきます。

gtest では、
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
                 SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
のように設定され、システムの処理が行われないようにしているからです。

XML が出力されない
さて、ここで困ったことがあります。
この状態では、テスト結果の XML が出力されないのです。
XML が出力されていない時点で「何らか」の失敗があったことはわかりますが、
できることなら XML が出力されて欲しいものです。

XML 出力されるようにしてみる
「無効なパラメータ ハンドラ」を設定します。
それには、_set_invalid_parameter_handler 関数を使用します。
こちらの第一引数にハンドラの関数ポインタを渡します。

void _invalid_parameter(
   const wchar_t * expression,  // 引数式
   const wchar_t * function,    // CRT 関数の関数名
   const wchar_t * file,        // CRT ソースファイル名
   unsigned int line,           // CRT ソースファイルの行
   uintptr_t pReserved
);

そして、このハンドラで例外を投げるようにします。(例外の内容はなんでもいいです。)
あとは、RUN_ALL_TESTS の前で _set_invalid_parameter_handler を読んで登録するだけです。

まとめたコードがこちら
#include <gtest/gtest.h>

static void OnInvalidParameter(const wchar_t * , const wchar_t *
    , const wchar_t * , unsigned int , uintptr_t)
{
    throw std::invalid_argument("invalid parameter error");
}
int main(int argc, char* argv[])
{
    ::testing::InitGoogleTest(&argc, argv);

    _set_invalid_parameter_handler(OnInvalidParameter);

    return RUN_ALL_TESTS();
}
TEST(CRT, strcpy_s)
{
    const char a[] ="test";
    char b[2];
    ASSERT_EQ(0, strcpy_s(b, a));
}

実行すると、失敗がレポートされ最後まで実行されます。


最後に
今回のケースで問題になることって、極稀だと思います。
ただ私の場合、身近なところで実際に問題になったことがあって、
それからこのことを初めて知りました。
プログラムが終了するパターンの一つなので、知っておいてソンはないと思います。

以上。

2012年8月5日日曜日

iutest v1.0 リリース

iutest v1.0.0.0 をリリースしました。

そして、さっそく v1.0.1.0 をコミット!
v1.1 に向けての第一歩です。

v1.1 では、比較的細かい修正のみになると思います。
それ以降で、DEATH テストやスレッド関係の対応をしようと思っています。


あとは、C言語バージョンもヒッソリ開発してますので、
ご意見頂けると嬉しいです。