2016年9月26日月曜日

[Visual C++] lambda を使った構造化例外と C++ 例外の処理

VC++ には構造化例外処理(Structured Exception Handling、通称SEH)があります。
これは C++ の try - catch とは別に __try - __except で処理することができます。

さて、この独自拡張で問題になること、というかメンドクサイことナンバーワンは、
1つの関数で try と __try を同時に使えないことではないでしょうか?

つまり、こういうことです。
void f()
{
    try {
        __try {  // error C2713: 関数ごとに許されている例外ハンドルのフォームは 1 つです。
        } __except(EXCEPTION_EXECUTE_HANDLER) {
        }
    } catch(...) {
    }
}

void g()
{
    __try {
    } __except(EXCEPTION_EXECUTE_HANDLER) {
    }

    try { // error C2713: 関数ごとに許されている例外ハンドルのフォームは 1 つです。
    } catch(...) {
    }
}
void fa()
{
    __try {
    } __except(EXCEPTION_EXECUTE_HANDLER) {
    }
}
void fb()
{
    try {
        fa(); // OK
    } catch(...) {
    }
}

lambda があるじゃない
Visual Studio でも lambda が使えるようになってます。これ使えばわざわざ関数にしなくても済みます!

void f()
{
    try {
        []() {
            __try {}
      __except(EXCEPTION_EXECUTE_HANDLER) {}
        }();
    } __except(EXCEPTION_EXECUTE_HANDLER) {
    }
}

やったね!

とはならない…

VS2012/2013 でエラー
上記コードは VS2015 なら問題なくビルドできます
しかし、VS2012/2013 ではエラーとなってしまいます。
(エラー内容は lambda 使う前と同じ、「error C2713: 関数ごとに許されている例外ハンドルのフォームは 1 つです。」)

もう少し詳しく書くと、こう。

void f()
{
    __try {
        []() {
            try {}
            catch( ... ) {}
        }();
    } __except( EXCEPTION_EXECUTE_HANDLER ) {
    }
}

void g()
{
    try {
        []() {
            __try {} // error C2713: 関数ごとに許されている例外ハンドルのフォームは 1 つです。
            __except( EXCEPTION_EXECUTE_HANDLER ) {}
        }();
    } catch( ... ) {
    }
}

void h()
{
    auto x = []() {
        __try {}
        __except( EXCEPTION_EXECUTE_HANDLER ) {}
    };
    try {
        x();
    } catch( ... ) {
    }
}

__try の中に try がある場合は OK
try の中に __try があるのは NG
lambda が try の外で定義されいれば OK

という感じでした。

まとめ
Visual Studio 2015 を使おう!

2016年9月20日火曜日

GO!!

ポケモンGO みんなやってますね。
自分は今のところやる予定がないのですが(端末の買い替えしないと無理)、周りが Go Go うるさい言ってるのでなんかせねばと…そこでこのネタですよ…何番煎じでしょうね…


ともあれ、
Go は今まで使ったことなかったので、いい機会なので私も Go をやってみました。



まずはオンラインコンパイラーで始める
とりあえず、オンラインコンパイラーを使って始めるのが一番簡単だと思います。
私が知っている Go言語 対応しているオンラインコンパイラーは以下があります。
Go Playground
Paiza.IO

今回はたまーに使ってる Paiza.IO でやってみたいと思います。
package main
import "fmt"
func main() {
  fmt.Println(" ʕ ◔ϖ◔ʔ  ゲットだぜ!")
}





あ、はい。なんかすみません。
もう遅いですよね…まじめにやります。

マスコットキャラクター
さて、上で某キャラになっていたのは、GO言語のマスコットキャラクターです。

What is "Go" Gopher?





うーん。まだ私には魅力がわからないようです。
次。
Windows での環境構築
ここからはローカル環境で Go言語 を使えるようにしていきたいと思います。
ダウンロード
まずは、こちら(https://golang.org/dl/)からインストーラーをダウンロードします。
ダウンロードしたら、インストールします。特別なにか対応する必要はなく、手順に沿ってインストールすれば大丈夫です。

Hello,world
まず、Hello.go ファイルを作成します。Go言語の拡張子は .go のようです。
Hello.go に以下のコードを記入して保存します。
package main

import fmt "fmt"

func main() {
    fmt.Printf("Hello world.");
}

ビルドします。
go build Hello.go
とすると、実行ファイル Hello.exe ができます。
これを実行すると以下のような出力がでるはずです。


はい。できましたね。

それでは次は何かしら作ってみたいと思います。
が、それはまた次回ということにしたいと思います。

最後に
さて、これでビンゴカードの穴を1つあけることができました。








2016年9月12日月曜日

[Jenkins] BlueOcean beta 版がプラグイン管理に登場

公開されてました。
https://wiki.jenkins-ci.org/display/JENKINS/Blue+Ocean+Plugin
プラグイン管理からインストールできます。



(スクリーンショットは beta 3 ですが、既に beta 5 がリリースされてます。)

以前、ソースコードからビルドしてインストールする方法を紹介しましたが、
これからは単純にインストールするだけで良さそうです。
ブログズミ: [Jenkins] Blue Ocean を試してみる

2016年9月5日月曜日

git master ブランチの更新を svn trunk にコミットする CI 環境構築

先日 Jenkins で svn から git に commit / push するジョブの紹介をしました。
今回はその逆 git から svn に commit できるようにしましたので、そちらを紹介したいと思います。

環境
  • Git repo (github)
  • SVN repo (OSDN)
  • 適当な CI サービス(今回は Codeship を使用)
  • アクセス用公開鍵(Codeship 発行)

手順
  1. git/svn ともに公開鍵を登録しておく
  2. svn からチェックアウト
    svn co svn+ssh://path/to/trunk svn
  3. git からもクローンする(別フォルダ)
    git clone git@github.com:srz-zumix/iutest.git git-svn
    
  4. .svn フォルダを git のフォルダにコピー、 .git フォルダを削除し、svn 作業ディレクトリにする
    cp -r svn/.svn git-svn
    rm -rf git-svn/.git
  5. cd git-svn
  6. 削除されたファイルを svn delete する
    if `svn st | grep -q '^!'` ; then svn st | grep '^!' | awk '{print $2}' | xargs svn delete; fi
  7. 追加されたファイルを svn add する
    svn add * --force
  8. svn の HEAD からログを取得し、対応する git commit id を取得する
    これは svn のコミットメッセージを構築するときに使用します。
    export PREVCOMMIT=
    if `svn log . -l 1 | grep -q 'git@[0-9a-zA-Z]*'` ; then export PREVCOMMIT=`svn log . -l 1 | grep 'git@[0-9a-zA-Z]*' | head -1 | sed -e 's/.*git@\([0-9a-zA-Z]*\).*/\1/g'`; fi
    e 's/.*git@\([0-9a-zA-Z]*\).*/\1/g'`; fi
    echo $PREVCOMMIT
  9. git の HEAD ($CI_COMMIT_ID) からログを取得し、svn のコミットメッセージ用にファイル出力する
    git log $CI_COMMIT_ID -n 1 --pretty="%B%ngit@%H%nhttps://github.com/srz-zumix/iutest/commit/%H" > ../svn.msg
  10. PREVCOMMIT があれば、そのコミットから HEAD までのログもコミットメッセージに追加する
    if [ -n "$PREVCOMMIT" ]; then git --no-pager log $PREVCOMMIT..$CI_COMMIT_ID^ --pretty="---------------%n%B%ngit@%H%n" >> ../svn.msg; fi
  11. svn commit する
    svn commit --file ../svn.msg

実際に動作しているところを見てもらいたいところですが、Codeship は private で見れないので割愛させて頂きます。



さて、これで github に push すると自動で svn も更新できる環境ができました。
現在 iutest v1.6.0 リリースに向けて開発中ですが、こちらの開発から git での開発に移行をしました。
バグとか typo とかあると思うので、是非是非プルリクして頂ければと思います。

では。


2016年9月2日金曜日

[雑記] ブログが紹介された

8月某日、私のブログ記事を紹介したいとの連絡が来た。
6年もブログ書いているとこんなこともあるもんなんだなーと、ちょっと嬉しくなりましたね。
で、紹介記事が公開されたのでご紹介。

紹介している記事はこちらで、

紹介された記事はこっち、

それかーって思いました。(Jenkins とか Cppcheck とか Visual Studio とか紹介してくれてもいいのよw)
なんか適当に書いた記事なので、こんなん紹介してもらっていいのかな?って気がしますが…
まぁいっかー


では、また来週。