2014-06-30

Old New Thing: 未定義動作はタイムトラベルを引き起こす(他にもいろいろあるけど、タイムトラベルが一番ぶっ飛んでる)

Undefined behavior can result in time travel (among other things, but time travel is the funkiest) - The Old New Thing - Site Home - MSDN Blogs

久しぶりに紹介するRaymond Chenのブログ記事。

C言語とC++では、様々な部分が、ドラゴンの住まう地というレッテルを貼られている。いや、正式には、未定義動作とされている。

未定義動作が発動した場合、何でもありだ。例えば、変数は同時にtrueでもfalseでもありえる。John Regehrは興味深い例のリストをまとめて、未定義動作コンテストの受賞者もある。

以下の関数を考える。

int table[4];
bool exists_in_table(int v)
{
    for (int i = 0; i <= 4; i++) {
        if (table[i] == v) return true;
    }
    return false;
}

これがタイムトラベルと何の関係があるんだ、と読者は疑問に思うであろう。ちょっと待て、あわてんぼうさん。

まず、ループの処理に間違いがあることに気がつくはずだ。結果として、関数はループを終了する前に、table配列の最後の一つ後ろを読んでしまう。古典的なコンパイラーは、特にこれを気にしない。単に、(それが言語のルールに違反するものであるにも関わらず)配列の要素の範囲を超えた領域を読むコードを生成するだけだし、配列の最後の一つ後の要素が条件にあうならばtrueを返す。

一方、古典的ではないコンパイラーは、以下のような解析を行うかもしれない。

  • ループの最初の4回の実行で、関数はtrueを返すかもしれない
  • iが4のとき、コードは未定義動作を行う。未定義動作は何をしてもよいので、我輩としてはそんなの無視して、iは決して4にはならないものとして話を進める。(もし、この仮定が破られた場合、何か予期せぬことが起こるであろうが、まあ、そんなことはどうでもよい。未定義動作は、我輩にとっては何をしてもいいことなのだからな)
  • iが5の場合は、決して発生しない。なぜならば、iが5に到達するには、iはまず、4に到達しなければならない。吾輩は、すでにiが4には到達しないと看過しておるからだ。
  • 故に、すべての合法なコードパスはtrueを返すものである。

この結果、非古典的コンパイラーは、関数を以下のように最適化できる。

bool exists_in_table(int v)
{
    return true;
}

やれやれ、こいつはちっと変だな。関数は未定義動作によって最適化されたため、何もしなくなってしまった。たとえ値がtableに存在しなくても(アクセスするのが違法な5番目の要素にすらなくても)、関数はtrueを返すのだ。

さて、この非古典的挙動をもっと推し進めてみよう。コンパイラーは、未定義動作は決して起こらぬものと看過できる(なぜならば、もし起こった場合、コンパイラーは何でもすることが許されている)のであるから、コンパイラーは未定義動作を最適化の助けとできる。

int value_or_fallback(int *p) { return p ? *p : 42; }

上記の関数は、int型へのポインターを取り、ポイントしている値か、(もしポインターがnullの場合は)、フォールバック値である42を返す。ここまではいい。

さて、この関数にデバッグ用のコードを挿入してみよう。

int value_or_fallback(int *p)
{
 printf("The value of *p is %d\n", *p);
 return p ? *p : 42;
}

この新しい行には、バグがある。ポインターpをnullであるかどうか確認せずにデリファレンスしているのだ。この些細なバグは、様々な結果を引き起こす。非古典的なコンパイラーは、この関数を以下のように最適化する。

int value_or_fallback(int *p)
{
 printf("The value of *p is %d\n", *p);
 return *p;
}

なぜならば、コンパイラーは、nullポインターチェックは必要ないと看過するからだ。もし、ポインターがnullであれば、どうせprintfは未定義動作を引き起こすのであるからして、コンパイラーはポインターがnullの場合は、何でもすることが出来るのだ(これにはポインターがnull出ないがごとく振る舞うことも含まれる)

さて、これまだまだ驚くに当たらない。読者の中には、コンパイラーの最適化としてむしろ期待している仁もいるだろう(例えば、もし三項演算子がマクロの中に隠されていた場合、それがおそらくはfalseの場合、コンパイラーに除去して欲しいと思うだろう)

しかし、非古典的なコンパイラーは、このバグ関数を利用して、タイムトラベルを始めるのだ。

void unwitting(bool door_is_open)
{
 if (door_is_open) {
  walk_on_in();
 } else {
  ring_bell();

  // wait for the door to open using the fallback value
  fallback = value_or_fallback(nullptr);
  wait_for_door_to_open(fallback);
 }
}

非古典的なコンパイラーは、この関数全体を、以下のように最適化できる。

void unwitting(bool door_is_open)
{
 walk_on_in();
}

ハァ?

value_or_fallback(nullptr)という呼び出しは、すべてのコードパスで未定義動作を引き起こすとコンパイラーは認識する。この解析を前方に持ってくると、door_is_openがfalseであった場合、else分岐はすべてのコードパスで未定義動作であると認識する。つまり、else分岐全体が、到達不可能である。[2]

さて、タイムトラベルの時間だ。


void keep_checking_door()
{
 for (;;) {
  printf("Is the door open? ");
  fflush(stdout);
  char response;
  if (scanf("%c", &response) != 1) return;
  bool door_is_open = response == 'Y';
  unwitting(door_is_open);
 }
}

非古典的なコンパイラーは、解析結果を持ってきて、「もし、door_is_openがfalseであれば、挙動は未定義である」とし、函数を以下のように書き換えるかもしれない。

void keep_checking_door()
{
 for (;;) {
  printf("Is the door open? ");
  fflush(stdout);
  char response;
  if (scanf("%c", &response) != 1) return;
  bool door_is_open = response == 'Y';
  if (!door_is_open) abort();
  walk_on_in();
 }
}

これをみると、オリジナルのコードは、クラッシュする前にドアベルを鳴らすが、書き換えられた関数は、ベルを鳴らすのをスキップして即座にクラッシュする。これは、コンパイラーは過去に戻ってベルを鳴らさないようにしたともとれる。

この、「過去にさかのぼる」というのは、ファイルのような外部にみえるオブジェクトでも起こりうる。なぜならば、標準規格は未定義動作を引き起こした時、何でもありなことを認めているからだ。その何でもありというのは、タイムマシンに飛び乗って、fwriteを呼び出さなかったかのように振る舞うことも含まれる。

コンパイラーはタイムトラベルを引き起こすなど許されないと主張したとしても[1]、先行する処理がなかったことにされることはある。例えば、未定義の操作により、ファイルバッファーが破壊され、データは実際に書き込まれないということが起こりうる。たとえ、バッファーがフラッシュされたとしても、未定義の操作はftruncateを呼び出して、論理的に書き込んだデータを除去することがありうる。あるいは、作ったはずのファイルにDeleteFileを呼び出してファイルをデリートすることもあり得る。

これらの挙動はすべて、同じ観測効果を持つ。特に、先行する処理が発生しなかったようにみえる。それが実際に起きてなかったことにされたのか、最初から起こらなかったのかは、コンパイラー理論の上からは、どうでもいいことである。

コンパイラーは未定義処理の結果を時間をさかのぼって適用することもできるということだ。

[1] 標準規格は、明示的に未定義動作によるタイムトラベルを認めている。

しかし、もしそのような実行が未定義の操作を含む場合、この国際標準規格は実装に対し、そのような入力に対し、いかなる実行上の制約をも課すことはない(未定義操作に先行する操作をも含む)

[2] この変換を考える別の視点としては、コンパイラーはelse分岐はすべてのコードパスで未定義の挙動を引き起こすので、コードを以下のように書き換えるとみることもできる。

void unwitting(bool door_is_open)
{
 if (door_is_open) {
  walk_on_in();
 } else {
  walk_on_in();
 }
}

未定義動作では何が起こっても許されるというということを利用した例だ。この例では、「walk_on_inを間違って呼ぶ」という何かになる。

ボーナス小ネタ:未定義動作には、一見すると明らかではない場合もある。例えば、nullポインターをデリファレンスするのは、何か危険なことをする前にデリファレンスの対策をしたとしても、依然として未定義動作になる。

int *p = nullptr;
int& i = *p;
foo(&i); // undefined

&と*は、お互いに打ち消しあい、あたかもfoo(p)と書いたかのようになると考えるかもしれないが、存在しないオブジェクトへのリファレンスを作った時点で、使わなくても、未定義動作を引き起こすのだ(§8.5.3(1))

参考文献:なぜすべてのCプログラマーは未定義動作について知らねばならないのか。Part 1, Part 2, Part 3

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

ところで、6月28日に土曜日に開催したドワンゴC++勉強会#1は、あまりにも本物のC++プログラマーを呼んでしまった。本物のプログラマーは怠惰を美徳とするものである。また、本当に必要になるまで行動しないものである。そのため、二人とも、勉強会の前日、当日にスライド資料を作成するという、エクストリーム資料作成を敢行していた。

また、にわかにでっち上げたドワンゴC++勉強会#1は、どうやら出勤扱いになるらしく、筆者には振替休日が与えられた。振替休日となるべき日は筆者が自由に設定できるので、もちろん、図々しくも今度の月曜日に設定して申請しておいた。

今後も勉強会は積極的に開催していきたい。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

新たなC++世代

先日のドワンゴC++勉強会で、筆者は若いC++世代と話をする機会を得た。若いとはいえ、筆者よりせいぜい5,6年歳が離れているだけで、C++を学び始めた歳も、筆者より5,6年遅かったので、都合10年ほど、筆者より後にC++を学び始めたというだけの話だ。しかし、C++にとって、いやプログラミング全般にとって、10年はあまりにも長過ぎる。

筆者がC++を書物で学び始めた頃、まだテンプレートはまともに実装されていなかった。筆者がコンピューターを所有し、C++を実際にコンパイル出来るようになった時、ようやく主要なコンパイラーがC++を実装し始めていた。当時最新のテンプレート事情を解説した、C++ TemplatesやC++ Template Metaprogrammingを、筆者は読んでいた。C++ Templatesは、10年後の2013年に日本語に翻訳された。当時最新だった内容は、今となっては歴史的資料でしかない。

そう、筆者の次の世代は、C++を学び始めた時からautoがあり、decltypeがあり、Variadic Templatesがあるのだ。当時、我々が必死に技巧を弄してエミュレートしていた機能が、ネイティブに存在するのだ。

ああ、もう新しい世代の時代なのだ。

ところで、ドワンゴC++勉強会では、CFrontを当時現役で使っていたという世代の人にもあった。筆者は、CFrontは文献でしか知っていなかったので、驚いてしまった。しかも、まだテンプレートが実装される前のCFrontを使っていたらしい。もっと話を聞きたかったものだ。

ドワンゴ広告

この記事はドワンゴ出勤前に書かれた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-06-29

ドワンゴC++勉強会#1を開催した

去る6月28日に、歌舞伎座タワーのドワンゴのセミナールームで、ドワンゴC++勉強会 #1を開催した。

今回は、でちまるさん(実際かわいい) (decimalbloat)と、狂える中3女子ボレロ村上/陶芸C++er (bolero_MURAKAMI)を発表者として招いて、最強の勉強会を行った。

ボレロ村上は、コンパイル時メタプログラミングで、レイトレーシングや波形生成などを行っている。本職は岡山の陶芸家である。

この日の発表は、テンプレートの再帰深度を下げる話や、コンパイル時レイトレーシング、波形生成、またC++の標準ライブラリのうち、constexprに対応できるものがまだまだあるという話であった。

でちまるさんは、Cプリプロセッサーでメタプログラミングを行っている。本職は艦これプレイと艦これ関連のコンテンツ収集である。

この日の発表は、いかにして数値というものを解しないCプリプロセッサーで四則演算を行うかとか、再帰もないのに現実的な回数のループを実現するかという、Cプリプロセッサーメタプログラミングにおける基本的な考え方から発表した。結局は、すべてをマクロ名の結合と置換で強引に行ってしまえばいいのだ。

Cプリプロセサーメタプログラミングに使われている極めて強引な手法を、彼はかの有名なニンジャスレイヤーのレッドゴリラ=サンの名言、「何事も暴力で解決するのが一番だ」を引いて説明した。言語というものは、以下に制限を加えようとも、必ず乱用されるものである。

なお、でちまるさんは今回のCプリプロセッサーメタプログラミング発表のまとめとして、「PHPを使え」というありがたい結論を提示した。

今回は、C++界で異彩を放つ強力な二人の発表者を呼んだので、発表内容は極めて濃くなった。二人の発表内容は、いったい何の役に立つのかと思った人もいるかもしれぬ。しかし、これらの技法は、C++の新機能を設計する上で、非常に参考になっているのだ。

筆者は、C++の歴史と題して、C++が作られた経緯や、最近の日本のC++標準化委員会の事情を説明した。

C++の歴史スライド資料

さて、LT発表は5人。

最初の発表者、南山まさかず@東京 (minamiyama1994)君は、テンプレートと依存型(C++の規格用語の依存型ではない)として扱う方法について発表していた。残念ながら、筆者には理解できない世界の話であった。

次の発表者、抹茶ココア (fimbul11)さんは、C++14にライブラリとしても追加されたinteger sequenceの技法や、テンプレートの再帰深度を線形増加より押さえる技法について発表した。

ぽんこつ@MyFleetGirls開発中 (ponkotuy)さんは、いかにCocos2dxがC++的ではないかということについて発表した。発表を聞く限り、Cocos2dxはクソであるという認識を得た。

かるぱねるら (karupanerura)さんの発表は、なぜか記憶に残っていない。たしかCocos2dxについてクソであると言っていた気がするが、はて。

ψ(プサイ) (tikal)ちゃんは、かわいい狐のコスプレをしていた。なんでも、いなり、こんこん、恋いろは。に出てくる、コンというキャラクターであるようだ。コンちゃんはvalgrindという、実行時メモリチェッカーについて発表した。Cocos2dxは非常にクソであると言っていた。また、AMDやnVidiaの不自由なドライバーの中のクソコードがよくvalgrindのチェックに引っかかったりしてムカつくということも言っていた。

ドワンゴC++勉強会は、ドワンゴらしく、ニコ生による配信も行った。

ドワンゴC++勉強会 #1 - 2014/06/28 14:00開始 - ニコニコ生放送

問題は、当日使っていたケーブルに不備があったので、急遽ドワンゴ社員が買いに走るなどという障害に見舞われたそうだ。

今回、connpassにて参加者を募集したところ、90人枠が一日と立たずに埋まってしまった。どうやら、C++勉強会には相当の需要があるようだ。今回、参加できなかった人達のためにも、これからも頻繁に開催していきたい。

筆者がドワンゴに入社してから、セミナールームを使って勉強会を積極的に開いてほしいとは言われていたものの、他の社員への負担などを考えて、今まで勉強会を開くことはなかった。今回、勉強会を開いてみたところ、予想以上の応募数があったので、これからは積極的に勉強会を開催したい。

今回の勉強会は、だいぶ重い内容であったので、次の勉強会は、バランスを取るために軽くしたい。そもそも、勉強会は自分で発表してこそ勉強になるので、次回の勉強会は、一般の発表者を多く募集したいところだ。とにかくC++WG論文を早く読まねばならない。

ドワンゴ広告

この記事はドワンゴ勤務外に書かれた。この勉強会がドワンゴ勤務に当たるのかどうかまだ分からない。仕事であるとすれば、休日出勤となるので、振替休日がもらえるはずである。しかし、今は読むべきC++WG論文が大量にたまっているし、それにサボろうと思えばいくらでもサボれるので、どうでもいいことである。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-06-26

誰かから送られてきたコスプレ衣装

昨日、妖怪ハウスに筆者の宛名でアマゾンからダンボールが送られてきた。はて、これ以上何かを注文した覚えはないがと不審に思いながら開けてみると、コスプレ衣装だった。送られてきたのは、おそらくは、このアサシンクリードのコスプレ衣装だ。

コスプレ衣装とあって身構えたが、どうやら、それほど奇抜でもない青いパーカージャケットのようだ。デザインは左右非対称で、右側にチャックがついている。左胸部分にも短いチャックがついているが、これは飾りでポケットではなく、開けても裏地がみえるだけだ。

私の趣味にはあわないが、この程度のデザインならば、普段着にできる人はできるだろう。実際、妖怪ハウスの住人の一部は、欲しいと言っていた。

2014-06-25

Clangが現在実装しているC++1z機能

注意:この記事の内容はC++17の正式な規格では変わっている可能性が高い。

Clang - C++1z, C++14, C++11 and C++98 Status

C++1z、あるいはC++17と呼ばれているC++の次期メジャーアップ規格に提案中の新機能のうち、Clangがすでに実験的実装を行っているものがある。これは、コンパイラーオプションに-std=c++1zを指定することで使うことができる。実装されている機能は、いずれも、まだドラフトにすら入っていない、提案論文しかない機能である。

本記事の執筆現在、Clangの-std=c++1zで実験的実装がされている提案は以下の通り。

N3928: static_assert with no message

C++11で追加されたstatic_assertは、必ず文字列リテラルを指定しなければならない。

// エラー
static_assert( true ) ;

// OK
static_assert( true, "" ) ;

文字列リテラルを指定したくない場合でも、必ず文字列リテラルを書かなければならない。これは極めて面倒で冗長だ。

そこで、N3928提案では、文字列リテラルを取らないstatic_assertの文法を追加する。

// OK, N3928提案
static_assert( true ) ; 

N3981: Disabling trigraph expansion by default

既存の巨大なコードベースを検索したところ、トライグラフは一切意図的に使われていないことが判明した。トライグラフが使われているのは、トライグラフによる置換を防ぐためのエスケープと、コンパイラーやCプリプロセッサー実装のテストコードの中だけであった。トライグラフには現実の需要がない上、コードを書く妨げになっている。N3981では、トライグラフを取り除く提案をしている。

以下のコードを考える。


#include <iostream>

int main( )
{
    std::cout << "??=" << '\n' ;
}

このコードを実行した結果、現行規格ならば、"#"が出力され、N3981提案では、"??="が出力される。

N3994: Terse range-based for loops

rage-based for loop、for ( elem : range )を、for ( auto && elem : range )に置き換える軽いシンタックスシュガーの提案。

// N3994提案
int main()
{
    char range[] = "hello" ;

    // for ( auto && elem : range ) と同等 
    for ( elem : range )
    {
    // 処理
    }

}

なぜauto &&なのかについては、色々と理由があるので、詳しくは論文を参照。

N4051: Allow typename in a template template parameter

テンプレートテンプレートパラメーターは、文法上、classキーワードしか使えなかった。

// 現行規格
template <
    template < typename T >
    class U // ここにtypenameキーワードは使えない
>
struct X { } ;

テンプレートテンプレートパラメーターに渡せる型がクラス型しかなかった昔はともかく、今は、エイリアステンプレートがある。そこで、typenameキーワードも許可する提案。

// N4051提案
template <
    template < typename T >
    typename U // classでもtypenameでもよい
>
struct X { } ;

以上、小粒な新機能の実装が多い。これらは実装がそれほど難しくもないし、おそらくは、ドラフト入りして制式採用される機能だと思うが、最初に警告したように、まだドラフト入りすらしていない機能であるので、注意されたい。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

今日、社内のくだらない雑談チャットで、ドワンゴに必要なのは社内猫であるという意見が出た。ネコアレルギーの社員との兼ね合いは難しいだろうが、猫のいる職場は、確かに生産性が下がるのですばらしい。あれ? なにか違う気がする。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-05-pre-Rapperswil mailingのレビュー: N3980-N3989

引き続き、2014-05-pre-Rapperswil mailingをレビューしていく。

N3980: Types Don't Know #

「型はハッシュのことなんざ知ったこっちゃねえんだよ」という挑発的なタイトルの論文

ある型をunorderedコンテナーに対応させるには、ハッシュ値が計算できなければならない。ユーザー提供したクラスは、ユーザーが自力でstd::hashを特殊化してハッシュ値の計算を実装しなければならない。問題は、適切なハッシュの計算というのは、極めて難しい技術であり、そんじょそこらの並のプログラマーは正しく書くことが出来ない(我は書けるなどと豪語するのはバカの証拠である)

これまで、N3333N3876で、バカでもユーザー定義型をハッシュ対応させられるようにしようという提案が出ていたが、これはどちらも、std::hashに既存の対応した型を放り込んでハッシュ値を生成するのを楽にしようというライブラリであって、汎用性に欠ける。

そこで、ハッシュアルゴリズムをテンプレートで変えられるようにし、また、演算子を定義するかのようにクラスをハッシュ計算に対応させられる新たなライブラリ、std::uhashを提案している。

「型はハッシュの事情など知らぬ」というのは、型はハッシュ値がどのように計算されるかという事情など知ったことではないし、知るべきでもないということだ。型が知っているのは、型のオブジェクトを区別化するための情報だ。ハッシュ値計算に必要な、オブジェクトが等しいか状態にあるかどうかに関わる情報を、ハッシュ値計算に混ぜ込む方だ。ハッシュ値がどのように計算されるかという内部事情を知る必要はない。

N3980では、ハッシュ計算に対応させたいクラスに、friend関数hash_appendを定義させる。そして、hash_appendをADL経由で呼び出す。

class X
{
    int i ;
    std::vector<int> v ;

public :
    template < typename HashAlgorithm >
    friend
    void
    hash_append( HashAlgorithm & h, X const & x ) noexcept
    {
        // unqualified lookupでADLを発動させ、
        // ADL経由で見つからなかった時にstd::hash_appendを発見できるようにするための
        // 小汚いテクニック
        using std::hash_append ; 

        hash_append( h, x.i, x.v ) ;
    }
} ;

このように、std::hash_appendをusing宣言で関数のブロックスコープに引っ張りこんでおいた上で、unqualified lookupでhash_appendを関数呼び出しする。すると、ADLで発見されるhash_appendと、std::hash_appendが等しくオーバーロード解決の候補となり、最適な関数が呼び出される。

クラス定義内でfriend関数定義をしているので、このhash_appendは、ADL経由でしか呼び出すことが出来ない。

実際にハッシュを計算するのは、テンプレート引数HashAlgorithmによって、ハッシュ計算に必要な情報を指示する部分から切り離している。

最終的に、ハッシュ計算はビット列をhashAlgorihmに渡すところにまで落とされる。

さて、hash_appendは、operator ==と密接に関係している。すなわち、

  1. x == y ならば、xとyは、hash_appendに同じメッセージを送る
  2. x != y ならば、xとyは、hash_appendに異なるメッセージを送る

オブジェクトが等しいならば、同じハッシュ値が計算されて欲しいので、同じ情報が送られなければならない。オブジェクトが等しくないのであれば、異なる情報が送られなければならない。ということだ。

たとえば、vectorを考える。vectorのoperator ==は、size()を比較してから、要素を比較すると定義されている。このため、vectorのhash_appendは、size()をハッシュ計算のメッセージとして送るべきである。

なぜか。もし、size()がハッシュ計算に使われなければ、以下の二つのオブジェクトが、ハッシュ計算では等しいメッセージとして見えてしまう。

std::vector<std::vector<int>> v1{};
std::vector<std::vector<int>> v2{1};

もしsize()をハッシュ計算に使わないと、v1は空なので何もメッセージを送らない。v2は内側のvectorを送るが、内側のvectorは空なので、ハッシュ計算に使うべき情報を送らない。したがって、どちらも同じメッセージになってしまう。

このため、size()をハッシュ値計算に混ぜ込む必要がある。問題は、size()は先に送るか後に送るかということだ。先に送る場合、std::forward_listのようなコンテナは、size()を計算するのにコストがかかるため、コンテナーは後に送るということで統一しようと論文は提案している。

ハッシュ値の計算には、contiguously hashableという概念がでてくる。これは、あるT型の任意の値x, yに対して、x == yならば、memcmp(addressof(x), addressof(y), sizeof(T)) == 0 がtrueとなることである。つまり、x == yならば、xとyは全く同一のビットパターンを持たねばならない。また、パディングビットのような、任意の値を取れるようなビットがあってはならない。

論文では、ある型Tがcontiguously hashableかどうかを調べるtraits、is_contiguously_hashable<T>を提案している。

整数が2の補数表現の環境の場合、intはcontiguously hashableである。

IEEE浮動小数点数は、contiguously hashableではない。なぜならば、0 == -0ではあるが、0と-0のビットパターンは同一ではないからだ。したがって、IEEE浮動小数点数を使う環境では、ハッシュ計算には特別なはからいをしなければならない。

boost::hash_combineとの違いは、hash_appendはビット列をそのまま送り込むのに対し、hash_combineは、個々にハッシュ値を計算し、複数のハッシュ値から、そこそこ使えるハッシュ値を計算するものである。hash_appendの方がハッシュ値計算をネイティブにサポートしている。

hash_appendはVariadic Templatesで実装されていて、引数をいくつも渡せる。

現在、ハッシュ計算としてよく使われているアルゴリズムで、N3980提案で効率的に実装できないものに、CityHashがある。これはCityHashは、後ろから計算していくためである。

とはいっても、CityHashと同等の計算速度や品質をもったアルゴリズムは他にもあるので、CityHashを考える必要はないとしている。

また、このライブラリは、SHA-2などのセキュアなハッシュ値計算に使うためにも転用できる。

pimplにどのように対応するかという問題は、HashAlgorithmをstd::functionでラッパーしてtype erasureすることにより、仮想関数呼び出しで実行時に呼び出し先を決定することができるとしている。

また、unorderedコンテナーのハッシュ計算は、同じ数と値の要素をもつコンテナー同士で同一のハッシュ値を計算する方法は、ないこともないが、どれも一長一短で、汎用的な方法がないため、この提案では規定しないとしている。

この論文を読むのは時間がかかった。

N3981: Removing trigraphs??!

トライグラフを規格から削除する提案。タイトルが面白い。??!はトライグラフで|に置換される。

ある巨大なコードベースに対して、トライグラフ風の文字列を検索した所、

  • 923件のトライグラフ置換を防ぐためにエスケープされた?

    string pattern() const { return "foo-????\?-of-?????"; }
    
  • 4件のトライグラフが、意図的にテストコードで使われていた。コンパイラーのためのテストコード2件と、boostのプリプロセッサーライブラリのテストコード2件。
  • 0件のトライグラフが、意図的にプロダクションコードで使われていた。

明らかに、トライグラフはC++の足かせになっている。

論文は、規格からトライグラフを削除する提案をしていて、そのための文面も提示している。

N3982: Rvalue reference overloads for optional

optionalのメンバー関数、valueとoperator *にref-qualifierがrvalueリファレンス版のオーバーロードを追加する提案。これはむしろ、バグフィクスと言える。

[せっかくやる気になっていたのに忌々しいPDF] Hashing tuple-like types

N3980とは違って控えめな提案。

std::pair, std::tuple, std::arrayをstd::hashに対応させる提案。これにより、tupleなどをunorderedコンテナーに突っ込める。

[嫌気が差すPDF] N3984: Adding attribute reflection to C++.

よくわからない変な提案。TSへの提案のようだが、あまりに違和感を覚える機能のためだろうか。また、どうもサンプルコードに誤りが多い。

どうも論文の記述が詳細ではないので、よく理解しにくいが、この提案は、クラスに、初期化子が書かれたattributeをクラスに付加し、typedefキーワードを使った文法でconstexprインスタンスとして取り出す機能である。typedefキーワードを使った文法は、N3951提案を拡張している。


struct serializable { } ;

struct getter { std::string name ; } ;
struct setter { std::string name ; } ;

struct [[serializable]] X
{
private :
    int index_ ;

public :
    [[ getter{"index"} ]] int index() const { return index_ ; }
    [[ setter{"index"} ]] void set_index( int value ) { index_ = value ; }
} ;

// std::make_tuple( serializable() )  
auto t1 = std::make_tuple( typedef<[[X]]>... ) ;

// std::make_tuple( getter{"index"} ) 
auto t2 = std::make_tuple( typedef<[[&X::index]]>... ) ;

// std::make_tuple( setter{"index"} )
auto t2 = std::make_tuple( typedef<[[%X::set_index]]>... ) ;

このように、クラスやメンバーにattributeを付加し、またtypedefを使って、constexprインスタンスとして取り出すことができる。

また、typedefにはrequires Cという文法で、取り出すattributeをフィルターできる。Cはテンプレート型引数ひとつとり、typedefでattrributeが返されるか否かをboolを返すconstexpr関数である。


struct Bogus { std::string str ; } ;
struct FuckingWhat { std::string str ;} ;
struct this_attribute_is_bullshit { std::string str ; } ;
struct awesome { std::string str ; } ;

template < typename T >
constexpr bool is_awesome
{
    return std::is_same_v<T, awesome> ;
}

struct [[
    Bogus{"Don't mind me."},
    FuckingWhat{"Seriously, I am useless attribute."},
    this_attribute_is_bullshit{"What did you expect huh?"},
    awesome{"I am just awesome."} ]]
X { } ;

/*
    std::make_tuple(
        Bogus{"Don't mind me."},
        FuckingWhat{"Seriously, I am useless attribute."},
        this_attribute_is_bullshit{"What did you expect huh?"},
        awesome{"I am just awesome."}  ) 
*/
auto t = std::make_tuple( typedef<[[X]] >... ) ;

// std::make_tuple( awesome{"I am just awesome."} ) 
auto t = std::make_tuple( typedef<[[X]] requires is_awesome >... ) ;

また、has_attribute<X, A>というtype tratisが追加される。これは、ある型XがattributeとしてA型、もしくはAから派生する型を持っている場合trueを返す。


struct Base { } ;
struct Derived { } ;

struct [[ Derived ]] X { } ;

std::has_attribute_v<X, Base> ; // true
std::has_attribute_v<X, Derived> ; // true

まあ、使い方はいろいろあるだろう。しかし、どうも個人的に、あまりにも文法や意味がわかりにくいコードに思えてならない。

[PDF注意] N3985: A proposal to add coroutines to the C++ standard library (Revision 1)

コルーチンライブラリの提案。Boost.coroutineを土台にしている。

とても重たい論文なので、軽く紹介するだけにとどめるが、std::asymmetric_coroutine<T>とstd::symmetric_coroutine<T>が追加される。

asymmetricなコルーチンとは、コルーチンが呼び出し元を把握していて、特別な操作によって、呼び出し元に実行を返すものである。

symmetricなコルーチンとは、呼び出し元だけではなく、任意のsymmetricなコルーチンに実行を移せる。

[PDFは切り詰められるべき] N3986: Adding Standard support to avoid padding within structures

クラスのパディングを無効にする文法を追加する提案。

C++では、クラスのサイズがいくつになるかは、規定されていない。

以下のようなコードを考える。

struct SomeDataStructure
{
    uint8_t type ;
    uint32_t data ;
} ;

ここで、sizeof(SomeDataStructure)は、1 + 4とはなる保証はない。たとえば、あるアーキテクチャでは、メモリは適切にアラインされていなければならないという制約があるかも知れない。そこで、コンパイラーはパディングと呼ばれる詰め物を挿入して、アラインを合わせようとする。

// このコードはパディングがないものとする
struct SomeDataStructure
{
    uint8_t type ;
    uint32_t : 24 ;
    uint32_t data ;
} ;

また、以下のようなコードを考える。

struct SomeHeader
{
    uint8_t : 4 ;
    uint8_t valid : 1 ;
    uint8_t : 1 ;
    uint8_t id : 2 ;
} ;

この場合、sizeof(FogFrameHeader)が1になる保証はない。なるほど、4 + 1 + 1 + 2は8ビットだが、コンパイラーがパディングを挿入しないという保証は、規格上存在しない。

しかし、このようなコードは、ビット列とその位置が重要なのであって、パディングを挿入してもらいたくないのだ。現実のコードでは、ディスク上のフォーマットや、ネットワークパケットのフォーマット、あるいはメモリを節約するハックなど、ビット列をパディングなしで明示的に指定したい需要が多くある。

このため、主要なC++コンパイラーには、パディングを無効にする独自の機能が提供されている。したがって、パディングを無効にする機能は、標準で存在すべきである。

N3986提案では、既存のビットフィールドの文法を拡張して、-1が指定された場合、次のビットフィールドをアラインせず、すなわちパディングを無効にする意味を持つ。

struct SomeDataStructure
{
    uint8_t type ;
    uint8_t : -1 ;
    uint32_t data ;
} ;

struct SomeHeader
{
    uint8_t : 4 ;
    uint8_t : -1 ;
    uint8_t valid : 1 ;
    uint8_t : -1 ;
    uint8_t : 1 ;
    uint8_t : -1 ;
    uint8_t id : 2 ;
} ;

もし、クラスSの-1ビットフィールドの次のメンバーtがビットフィールドではない場合、そのメンバーのオフセットは、offsetof(S, t) % sizeof(t) == 0を満たす必要がある。

struct S
{
    uint8_t c ;
    char : -1 ;
    uint32_t t ;
} ;

static_assert( offsetof( S, t ) % sizeof(t) == 0, "This shall not be asserted" ) ;

これはTS行きなのかもしれないが、パディングを無効にする機能は、標準で欲しいところだ。

[Yet another goddamn PDF] N3987: Yet another set of C++ type traits.

小粒だが有益な型情報を得るtype traitsを多数追加する提案。

is_default, is_delete, is_extern, is_explicit, is_export, is_final, is_friend, is_inline, is_mutable, is_noexcept, is_override, is_private, is_private_base_of, is_protected, is_protected_base_of, is_public, is_public_base_of, is_thread_local, is_virtual, is_virtual_base_of.

is_defaultとis_deleteは、default化やdeleted定義されたメンバー関数ならばtrueを返す。暗黙にdefault化やdelete定義された特別メンバー関数の場合はどうなるのだろうか。他にも、デストラクターは例外指定を基本クラスから暗黙に受け継ぐ。クラス定義内で定義されたメンバー関数は暗黙にinlineになる。こういう暗黙の型情報はどうなるのだろうか。

論文筆者に問い合わせたところ、明示的であろうが暗黙であろうが、結果には影響を及ぼすべきではないとの回答を得た。論文ではこの問題について明示的に考察していないが、するべきだと思われるので、次の改定版では言及するとのこと。また、暗黙的に指定されたかどうかを調べるis_implicitが必要かもしれないと言っていた。

また、ローカルクラスかどうかを返すis_localや、is_pure_virtual, is_ovberload, is_direct_base_ofなどといったtype traitsも挙げられている。

[PDFだ・・・] N3988: Towards restrict-like aliasing semantics for C++

C++にC99のrestrictの機能を入れるにあたっての議論をまとめた論文。

C99のrestrictを単純にC++に入れられない理由は、thisポインターを経由するクラスメンバーへのアクセス、リファレンスへのrestrict、restrictの有無がオーバーロード解決やテンプレート実引数推定に影響するかどうか、またlambdaキャプチャーなど、C99にはない問題を考える必要があるからである。

しかし、現実の主要なC++コンパイラーを観察すると、すべての主要なコンパイラーは、restrictキーワード、あるいは同等機能を、何らかの方法で実装している。明らかに需要がある。これは標準化が必要だ。

N3989: Technical Specification for C++ Extensions for Parallelism, Working Draft

<algorithm>にタグディスパッチで並列実行版とベクトル実行版を加えるTS(Technical Specification)への提案。

ドワンゴ広告

この記事はドワンゴ勤務中に書いた。これを書いている最中に、筆者の近くの席から、「ああ! 一瞬死んでもらえばいいのか!」という会話が聞こえてきた。実に、プログラマーの会話というのは、文脈を離れると物騒になるものである。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-06-24

ドワンゴC++勉強会のニコ生の番組宣伝

ドワンゴ広告

6月28日にドワンゴのセミナールームで行われる、ドワンゴC++勉強会 #1の、当時のニコニコ生放送の番組URLができた。

ドワンゴC++勉強会 #1 - 2014/06/28 14:00開始 - ニコニコ生放送

ドワンゴC++勉強会は、ニコ生による映像配信が行われる手はずになっている。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

ドワンゴ非広告

今、N3985を読んでいる。これはコルーチンをC++の標準ライブラリに追加する提案だ。設計は、Boost.Coroutineを土台にしている。よく書けている論文ではあるが、なかなか読むのに時間がかかる。今月は、個人的な環境に大変化が多数あったため、C++WG論文の読み込みが遅れている。さらに7月に次の論文集が控えているので、しばらく忙しくなるだろう。ちなみに、これはドワンゴにおける筆者の仕事ではない。ただ勤務中に勝手にやっているという扱いになっている。

妖怪ハウス宣伝

6月27日、28日の夜は、妖怪ハウスにあのボレロ村上氏が来るため、妖怪ハウスに来ると技術的な話で盛り上がれるだろう。何か大人数で食べられる食事を作ろうと思う。

7月6日は、妖怪ハウスでピザでも焼きながら、ボードゲーム会でもしようと思っている。

妖怪ハウスに来たい人は、筆者のTwitterかメールに連絡をすればよい。

2014-06-23

妖怪ハンモックその他の雑多な感想

ハンモックの話

妖怪ハウスにハンモックを導入したことは、すでに述べた。ハンモックは土台付きのものを買ったのだが、ついてきたハンモックは、あまり寝心地がよくない。調べると、もっと良さそうなハンモックも売られている。ハンモックの布自体は、それほど高くない。そこで、もう一枚ハンモックを買うことにした。

買ったのは OUTDOOR EX 2人用 耐荷重 200kg 布製 ハンモック 専用ポーチ 補強帯 S字フック 付 ストライプ(レインボー)だ。これは、耐荷重200kgで、相当に幅も広い。二人用だという。ひとつのハンモックで二人寝る場合、相手の選択は自然と選り好みをする必要があるだろうが、それはまた別の話だ。今回は一人で寝る快適性のみを検証する。

アマゾンで買って、すぐに届いたので、早速にも寝心地を検証したかったのだが、あいにくと、手持ちの土台には長さが余りすぎて取り付けられなかった。ベランダの手すりになら取り付けられそうだが、それにはテントをたたまなければならない。雨が上がったら試すつもりだ。

ところで、今週末、来週末は、どうやら妖怪ハウスに来ると面白くなりそうだ。

6月27日,28日は、岡山から陶芸constexprプログラマーの某氏がやってくるので、ちょっとしたパーティでも開こうと思っている。

また、7月6日は、ピザパーティでもしようかと思っている。どうやら、妖怪ハウスに遊びに来るには、何らかの口実が必要であると考える人が多いらしい。確かに、私もシェアハウスめぐりを続けたいと思っているが、最近は新しいシェアハウスには行っていない。いつ来てもいいとは言われていても、パーティなどの、何らかのいくための口実が必要だ。そこで、7月6日はピザでも焼きつつ残りのタピオカパールをゆでつつ、また適当な菓子でも作って人を呼び、ボードゲームパーティでもしようかと思う。

ストレスへの対処方法の話

最近、ストレスへの対応方法が真逆の人間を二人観測している。一人はストレスの発散として破壊活動を行う。もう一人は、ストレスを貯めこんで自己の肉体を破壊している。どちらがマシだろうか。私は前者のほうがまだマシである気がしてならない。その破壊対象が私と私の所有物に及ばなければの話だが。

SI屋の話

10年ほど前、筆者は当時2ch.netのプログラマー板で、SI屋の悲惨な現状を観測していた。その当時、下手な受注ソフトウェア開発会社に雇用されると、数年以内に精神を壊し、再起不能に陥るだろうと結論した。そのため、私は職を求めずに、己の欲するところを行った。その結果、今の不思議な立場を得た。今の立場を得る見込みは当時一切なく、またこの後何年続くかもわからないが、少なくともこれだけは言える。SI屋で働くよりはマシだ。

SI屋の問題は、結局、ソフトウェアやプログラミングという概念自体が理解できないバカな顧客を相手に利益を上げるところから来るのであろう。利益を最大にしようとすると、バカな顧客でも理解できそうなバカで無駄で不必要な作業を行って、その作業に金が必要なのだと説得にかかる。そして、顧客から金を得た以上、実際にバカで無駄で不必要な作業を行う。

住み分けてもらいたい。本物のプログラマーの素質を持った人間を、SI屋で潰さないでもらいたい。

東京に出てきてから半年たった話

東京に出てきてから、もう半年たった。実に、筆者の環境は劇的に変化した。環境の劇的な変化は、今も続いている。また、意図的に変化させるようにしている。

それにしても、周りの環境は劇的に変化したが、筆者自身は、あまり変化した実感がない。筆者は一つのことは数ヶ月で飽きるので、興味の対象がどんどん変化する。そういう意味では、東京に出る前と、あまり変わっていない日常と言える。

2014-06-22

Eric Meyerのレベッカに対する弔辞

Eric's Archived Thoughts: Eulogy

以下はレベッカの葬式における私の弔辞である。私が当日言ったこととテキストが一致しているといいのだが。この言葉を引き出した悲しみにより、私は正確な言葉を覚えていないし、また撮影された映像を見返す気力も今はない。五木力が湧くのかわからない。いつか見て、Carolynの言葉を聞きたいものだ。

レベッカはわんぱくであった。娘は生後二週間で、にらめっこコンテストで大人を負かした。レベッカは元気だった。娘の笑い声は部屋中に響き渡り、皆をほほ笑ませた。レベッカはがんこだった。たとえ、欲しい物を失ったとしても、娘は絶対に諦めなかった。レベッカは優しく、愛しく、わがままで、ああ、くすぐったがりだったな。

レベッカはやんちゃだった。歩くぐらいならスキップ、スキップするぐらいなら走る、走るぐらいなら踊る、踊るぐらいなら物陰に隠れて追いかけてきた人を脅かす。

娘は携帯電話や財布やカギをポケットから盗むのが好きであった、隠すのではなく、悪いことをするのでもなく、目の前で振りかざして、歌い踊るのであった。これ以上のことは、どうか娘から遠ざけてもらいたい。娘が到底できっこないことを目指すのを防ぐためではない。むしろあまりにも簡単にできてしまい、がっかりするのを防ぐために。

レベッカは天使ではなかったし、本人も天使となりたいとは思わなかった。レベッカは、いわばポルターガイストだ。六歳の誕生日に、その日と次の日は、遊園地に行こうと決めていた。そうとはならず、娘の命日となるとは。その日、水道管の故障により、遊園地は週末閉園した。娘が行けないのであれば、誰も行くべきではないからだ。今朝このことを話していて、私がまさに「電気なんか消えてしまえ」と言わんとしたとき、家が停電した。

ややクサい話だ。

娘の最後の数週間は、腫瘍が娘から元気をゆっくりと奪っていき、とてもつらかった。元気のない娘を見るのは耐えられなかった。娘の日常生活を快適にするために長年努力してきて、うまくいっていた。最後の数日は、その努力すらも無駄であった。

娘は、いつまでもレベッカであった。娘は兄弟が親のそばにいるのに、自分は近寄れないことに腹を立てていた。娘は兄弟のせいではないために、兄弟を許した。我々が娘を楽しませようとする努力がつまらないがために、娘は見下げた顔を向けた。娘は言葉もなく、しかし明らかに、大好きなお話をせがんだ。娘は、我々をこれ以上苦しめないよう、我々を遠ざけようとした。だが、我々の愛はいかなる苦しみにも代えがたいものであり、この愛は決して消えることがないと説明した時、娘はこの疑いようのない真実を認めた。娘の最後の言葉と仕草は、愛であった。

娘の最後の数時間は悲痛であった。一緒であったからこそ乗り越えてこられたのだ。コミュニティは我々を数カ月の間支えてくれ、レベッカとキャロラインと樹脂あのために、できる限りのことができた。コミュニティはこの問題を乗り越えさせてくれた。我々の心は数え切れないほど粉々のかけらになったが、拾い集めて元に戻す助けとなるだろう。娘がいなくなり、私は心を壊す以上に参っているが、私は決して、一瞬たりとも、娘を我が家に、我が生活に加えたことを後悔しない。

人生とは、自分が何を成し得たかではなく、他人に何を成し得たか、どんな業を残したが重要だ。娘の人生は短かったが、その光は時代に照り輝き、多くの人の心を温め、我々の残りの人生をより良くしてくれた。

妖怪ハウスにハンモックを導入した

さて、これまで妖怪ハウスには、レトロゲーム、まともなネットワーク機器、ゴミ箱、メタルラック、テント、大きな冷蔵庫、乾燥機付きの洗濯機など、様々なものを導入してきた。これにより、妖怪ハウスはだいぶ住みやすくなった。

しかし、まだ妖怪ハウスに欠けているものがある。ハンモックだ。

来たるべき夏に、ベランダにハンモックを設置して寝たら、さぞかし気持ちがよかろう、

なるほど、ハンモックはよろしい。しかし、ハンモックを吊るすべき場所がない。調べると、ハンモックを固定する土台が売っているようだ。これならば、十分な空間さえあれば、どこでもハンモックを設置できる。。

ハンモックは、東京に来た時から買いたかったが、色々と忙しく、また外も寒かったため、買わずにしまった。しかし、そろそろ余裕も出来たので、ひとつ買ってみることにした。アマゾンでは、手頃な商品として、7700円のMサイズと、14000円のLサイズのものがあった。せっかくなのでLサイズを買ってみることにした。

さて、ハンモックは昨日届いた。喜び勇んで開封し、ひとまずリビングに設置した。そして、その快適な寝心地に感動した。

その晩はハンモックで寝ようかとも思ったのだが、慣れない環境では睡眠の質が下がる可能性があるため、テントで寝た。夜間、激しく雨が降ったが、予め施しておいた防水対策で、こんどは浸水することはなかった。

ハンモックに対するさしあたっての不満は、袋から開封したばかりのネットが、何か接着剤のような臭いがするということだ。これは一度天日干しにする必要があるだろう。それには梅雨明けを待たねばなるまい。

rebeccapurpleがCSS 4 colorに提案された経緯

Name #663399 "Becca Purple" in CSS4 Color? - Specifiction

#663399を"Becca Purpule"としてCSS4 Colorに入れないか?

CSS colorに名前を追加する方法はわからないし、なにか目的に叶うものであるかどうかもわからないが、@meyerwebのCSSに対する貢献を明らかにするために、また標準化というのはそもそも社会的プロセスによって進められることを明らかにするために、#663399を"Becca Purple"と名付けないか?

これはいったいどういうことか。Beccaというのは、哀れにも六歳にして亡くなったEric Meyerの娘の名前なのだ。Eric MeyerはCSSの標準規格に尽力し、また、 Cascading Style Sheets: The Definitive Guideや、 Css Pocket Referenceといった本を執筆している。彼のCSSに対する貢献は甚大であり、彼の亡くなった娘のために、提案されたのだ。

この提案に対する、彼の声明は以下の通り

Eric's Archived Thoughts: rebeccapurple

beccapurple(#663399)をCSS規格に追加しようという提案と、その提案を取り巻く議論についてはすでに把握している。

この提案に対する賛成と反対意見のそれぞれについては理解できるが、明らかに、私はこの問題に立ち入って判断するには、あまりにも個人的に問題に密接すぎる。ついては、わたしはColor規格のエディターに、Working Groupの総意がどうあれ、受け入れることを伝えた。現在、WGはこの提案を議論中である。

私は条件をひとつだけ出した。もし、提案が受け入れられるならば、名前はrebeccapurpleでなければならぬ。私の娘が死ぬ数週間前、レベッカは、ベッカは赤ん坊の名前であり、六歳になったらビッグになってやるんだ、と我々に宣言した。六歳になった時、娘は自分のことは(単に私だけではなく皆から)ベッカではなくレベッカと呼んでほしいと望んでいた。

娘は6歳になった。十二時間もの間、娘は六歳であったのだよ。だからレベッカだ。レベッカでなくてはならぬ。

Katと私はコミュニティが気にかけてくれたことと支援に深く感動している。この提案は、個人的にとても大きなものである。たて、この提案が最終的に否決されたとしても、とても大きな意味を持つものである。私は常々、「推奨されるのは光栄である」というのは、すっぱい葡萄の上で踊るようなものであると考えていたが、どうやら違うようだ。本当に光栄である。結果がどうなるにせよだ。光栄であるにせよ、誰もそういうことを考えてのことではないのだから。

みんなありがとう。

Rebeccaの死の経緯

Eric's Archived Thoughts: The Truth

小さな小児精神科病院の低い壁際にあるソファに、レベッカを座らせた。レベッカはKatの膝の上に登り、私を、恥じらいといたずら心の入り混じった独特の表情で見た。私は娘の我々に寄せる信頼と、これから娘に伝えねばならぬことに耐えかねて呼吸困難に陥っていた。

「お前には言わなくちゃならないことがあるんだよ」

娘は目を伏せた。娘の表情なにか悲しげなものに溶けていった。知っているのだ、と私は考えた。知っているのだ。しかし、いずれにせよ我々は言わねばならぬのだ。

「悪い石のこと、覚えてる?」 娘は無表情に、ゆっくりと、とてもゆっくりと、体を持ち上げた。「お医者さんが取り除けなかった、頭の中にある腫瘍のことは覚えている? パパとママが悪い石を消すお薬を探していたのを覚えている?」

我々は娘が頷くのを待った。娘がこの問題を理解しているという証拠を。しばらくして、娘は逃げ場を探すように、キョロキョロしだした。

「お薬は見つからなかったよ。まだ探してるんだが、見つからないかもしれない」Katの顔から涙がたれた。私も顔を伏せているので、レベッカの顔をよくみることができぬ。娘は顔を下げて、Katから離れ、我々夫婦の間に座を占めた。

小さな、うめくような声「お前、分かっているのかい?」

沈黙

娘は頷いた。そして、顎が震え始めた。沈黙。さらにさらに震え始め、顔が歪み、すすり泣き始めた。後ろザマにのけぞり母親にもたれかかり、まだボールのように丸まりながら、絶望に泣く。避けられぬ死に対して。

我々三人はみな抱き合ってすすり泣いた。

上手く訳せないので、後はリンクのみ。

他にもまだあるので、Eric's Archived Thoughts: Rebeccaで。

訳し忘れていたが、rebecca purpleは規格入りするようだ。

Re: [CfC] adding 'rebeccapurple' color to CSS Color Level 4 from Daniel Glazman on 2014-06-21 (www-style@w3.org from June 2014)

From: Daniel Glazman <daniel.glazman@disruptive-innovations.com> 
Date: Sat, 21 Jun 2014 09:48:06 +0200
Message-ID: <53A538B6.3090400@disruptive-innovations.com> 
To: "www-style@w3.org" <www-style@w3.org> 

(co-chair hat on)

以下の提案はソーシャルメディアで公開された。この提案は、カラー名、rebeccapurpleを、値#663399にて、CSS Color Level 4に追加するものである。これは最近亡くなられたEric Meyerの娘を記念して、WebコミュニティがEricに支援を表明するためのものである。私は念の為にEricに了承を求めたが、Ericは「光栄に思い、喜んで受け入れる」と返答した。

一部の実装者(MOzilla, Apple, Google, Microsoft)は、この新しい値を実装してリリースすると明言している。

そこで、この提案へのコンセンサスを呼びかけるものである。

太平洋時間金曜日11:59PMまでに反対意見のないかぎり、私はコンセンサスが得られたものと宣言し、値をCSS Color Level 4に追加する。

期限までに反対意見がこのCfCに寄せられることはなかったので、私はコンセンサスを宣言する。Tab、'rebeccapurple'をCSS Color Level 4に付け加えてくれ。

記録のために書くと、私がEricにこの決定を連絡するように勧めたのはTabだ。なぜならば、EricがこのWGに在籍していた時、私も在籍していたからだ。私は今日中に連絡しておく。CSS WGを代表するのみにあらず、我々Webコミュニティ全体の代表として。

おめでとう!

</Daniel>

2014-06-19

Debianがeglibcからglibcに戻る

Debianはしばらく、libcとして、glibcではなく、glibcと互換性を維持したforkであるeblicを使っていたが、このたび、glibcに戻る決定をしたそうだ。

glibcを使っていた理由はいろいろあるが、Debianにとって重要なパッチが、glibcでは開発体制の問題により受け入れられないという政治的な理由もあったそうだ。その問題が解決されたのと、eglibcがプロジェクトとして死んだので、戻るのだそうだ。

Debian is switching (back) to GLIBC | Aurelien's weblog

5年前、Debianと多くの派生ディストロは、標準であるGNU C Library (GLIBC)から、Embedded GLIBC (EGLIBC)乗り換えた。Debianは、GLIBCに再び乗り換えることにする。EGLIBCの最後のリリースは2.19と、プロジェクトとして死んでいるからだ。現時点で、glibcパッケージがexperimentalにアップロードされ、 NEW queueにある。

EGLIBCが死んだのは、物事が良い方向に変わってきたからだ。GLIBCの開発体制は、ここ数年で、二つの大きな事件により、大きく変わった。Ulrich DrepperがRed Hatを辞めて、GLIBC開発から手をひいたのと、GLIBC steering committeが自然消失したからだ。この結果、協力的なチームワークによる友好的な開発体制に変わった。開発は今やピアレビューを基本とし、結果として不具合が減少した(人間は誤りを犯すものである)。昔ならば不可能であったことも可能になった、例えば、すべてのアーキテクチャで、同じレポジトリを使うとか、ports/ディレクトリを廃止するとかだ。かつては、二つのアーキテクチャー群に分かれていた。x86とかSuperHとかSPARCなどの主要アーキテクチャーは、主要レポジトリであるglibcレポジトリで、ARMとかMPSなどのアーキテクチャーは、副レポジトリであるglibc-portsレポジトリでサポートされていた。明らかに、分離には明確な理由はなく、変更が副レポジトリに適用され忘れることも多かった。それから、定期的な修正が行われる、本物の安定ブランチもできた。

ほとんどの重要なEGLIBCの機能はGLIBCにマージされた。例えばbashではなくPOSIXシェルを使うとか、予約語を変えるとかだ。まだマージされていないのは、設定可能なコンポーネントだ。これは、 Debian-インストーラーで使う予定で、NISとk PRCをサポートせず、-Osを使った軽量版を作るとかだ。結局、そういう開発はしなかったし、Debianの対象となるハードウェアは、GLIBCのサイズより早く発展していったので、それほどの損失ではない。最終的に、EGLIBCのツリーから取り込まれなかったパッチは、5個だ。

パッケージ名は変更されない(ソースパッケージとソースを含むバイナリパッケージは除く)ので、ユーザーからは変更は意識されない。

EGLIBCのために働いてくれたCodeSourcery社員と、EGLIBCの主要な変更をGLIBCにマージするために多大な時間を割いてくれた上に、マージ状態に関するメール定期的送ってくれた、Joseph Myers感謝する。そして、GLIBCの改革を実現してくれたGLIBC側の人々と、GLIBC開発に関わったすべての人々に感謝する。

ちなみに、Red Hatを辞めたUlrich Drepperは、ゴールドマン・サックスに移ったのだが、Reddit上では、これは2008年の経済問題を引き起こした張本人を罰するために移ったのだというジョークが書かれている。

Debian is switching back to GLIBC | Hacker News

結局、独裁者の存在は、長期的に見れば損失が大きい。

妖怪テント、リベンジ

妖怪ハウスのベランダに筆者がテントを設営したことは、いまさら言うまでもない。そのテントは、この前の梅雨入りの際の集中豪雨にあって、見事に水没してしまった。

テントを撤収し、布団を乾かして、失敗した理由を考えた。

まず、テントが地面に接しているのがまずいのであろう。地面に接していると、一度雨で濡れると、なかなか乾かない。これを防ぐには、テントを地面から浮かす必要がある。

そして、テントが水没した直接の理由は、テントの窓を開けていたことだ。フライシートを過信して、内側の窓を開けていたのが失敗だった。雨の日は窓を閉じるべきである。

雨が直接テントに当たることを低減するために、上にブルーシートを貼っていたのだが、これは完全に裏目に出てしまった。ブルーシートの上に水がたまり、危うくテントを押し潰すところであった。このために筆者は、雨の中、ブルーシートの上にたまった水をかき出す作業に追われた。

さて、今設置している妖怪テントは、妖怪ハウスに転がっていたベッドのパーツを下に敷くことで、テントを物理的に地面から浮かすことに成功した。

これから更に雨になる天気予報であるが、ひとまずこれで、雨に耐えられるかどうか実験してみよう。

あるいは、タープなるものを上に設置するのもよいのかも知れぬ。

なぜ筆者が様々な苦労をしてテントを設営しているのか。それは、一人で寝られる空間を作るためだ。睡眠は極めて重要であり、何者にも邪魔されてはならない。残念ながら、妖怪ハウスには個室がないため、何者にも邪魔されない空間がない。

ないものは作り出せばよいのだ。そこで、テントを設置した。結果として、実に快適な睡眠が得られるようになった。加えて、テントで生活するのは夢がある。

さて夢といえば、夏に向けて、ハンモックも買おうと思っている。やはりハンモックにも夢がある。スタンド付きで自立するものを買おうと思っている。

2014-06-18

妖怪ハウスでくさやをたべた

妖怪ハウスの同居人の一人が、休日に八丈島に釣りに行ってきた。釣りの成果は、はかばかしくなかったそうだが、おみやげとして、くさやを買ってきてくれた。くさやというものは、極めて臭いものであるという話だ。おみやげのくさやのパッケージは、真空パックされて、減塩、減臭と書かれている。開けると臭う懸念があり、よい機会もないので、数日放置していたのだ。

さて、今日の夜、酒を文化的に飲める人が妖怪ハウスにやってきたので、場の雰囲気で、我々は酒の肴にくさやを食べてみる決意をした。真空パックを開けたが、想定していたような臭さはなかった。しかしそれまで乗り気であった住人と客人が、何らかの理由ですみやかにリビングから消えていった。リビングに残ったのは、筆者を含めたオッサンが三人だけである。

我々は、さっそくくさやの賞味にかかった。くさやは、実に美味であった。酒によくあう。いや、これはうまい。実にうまい。世の中にこんなにうまいものが存在していたのか。

我々オッサン三人は即座にくさやをたいらげてしまった。こんなにうまいものをいい歳をしたオッサンばかりでたいらげてしまうとは、大人げないことだ。

念の為に歯を磨いた筆者は、他の住人と客人が避難した部屋を訪れた。筆者が取材した話によれば、くさやの真空パックを開けた瞬間、極めて強烈で不快な悪臭がリビングに充満したため、緊急避難したのであるという。筆者達がくさやをたいらげてしまったことを申し訳無さそうに告げても、彼らは残念な顔ひとつせずに、むしろ安堵の表情を浮かべるではないか。これはいったいどういうことだろう。

結論:くさやはうまい。

2014-06-17

ドワンゴにエクストリーム出社した

筆者がドワンゴに入社して、早六ヶ月がたった。現在、またC++WG論文がたまっているので、読み進めている。現在、N3980: Types Don't Know #を読むのに、思いのほか長くかかっている。筆者はあまりライブラリが得意ではないし、この論文は特に難しいと感じる。この提案は、型にハッシュの事情を考えさせずに、ハッシュ計算に必要な情報を混ぜ込むということを、演算子を定義するが如く簡単に行うための提案だ。ただ、ADLを使うのは個人的に気に食わない。

ところで、今日はドワンゴにエクストリーム出社した。その次第は以下の通りである。

筆者はドワンゴ社員には珍しく早寝早起きなので、午前中(11時50分)には出社のために家を出て、ドワンゴに向かった。西武新宿線は、なかなか電車が来ないので、駅ホームを何往復も歩いた。高田馬場で東西線に乗り換えたが、あいにくと、今日の東西線は、10時51分頃、「茅場町〜門前仲町駅間でトンネル内換気室からの発煙のため、ダイヤが乱れています。」とのことで、九段下までしか行けなかった。さてどうするか。

筆者は完全な裁量労働制であるので、遅延証明書をもらうなどと言った些細な問題を気にしなくてはよい。実に、遅延証明書をわざわざ取得するというのは、時間の無駄であり、筆者の理解の及ぶところではない。それはさておき、遅刻といった概念自体が存在しないものの、C++WG論文を読むためには、会社にいたほうが、現場で働いているエンジニア達の意見が聞けるため、色々と都合がいい。

アナウンスでは、13時頃には復旧の見込みだという。

なるほど、一時間もせずに復旧するわけだ。ならば、久しぶりに神保町に言って、古本でも見てこよう。筆者は九段下から神保町まで歩き、古本を漁り、ニーチェなどを購入した。再び歩いて九段下駅に戻ると、なんと、復旧予定が14時に伸ばされていた。埒が明かぬ。

再び神保町に取って返し、しばらく見物しながら歩いていた所、また東京メトロの駅入り口に出くわした。やはり、今日は東西線を諦めて、別の経路で出社したほうがいいだろう。みれば、たまたま丸ノ内線に乗れる駅であった。丸ノ内線は銀座駅に止まる。銀座駅から東銀座までは歩ける距離だ。

こうして、筆者はエクストリーム出社した。

ドワンゴ広告

この記事はドワンゴにエクストリーム出社した後の勤務中に書かれた。

ドワンゴには、水泳部、ダイビング部、ボルダリング部、スノーボード部など、エクストリーム出社に役立つ同好会がある。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-06-15

rm -rfしちゃったけどどうする

rm -rf remains

rm -rfの後に残りしもの

遊びのために、筆者は新しいLinuxサーバーを立ち上げて、rootでrm -rf /を実行して、何が残るかをみてみた。どうやら、今のrmというのは筆者のようなアホを相手にしなければならない未来に生きているようなので、実際に実行するには、--no-preserve-rootをつける必要があった。

# rm -rf --no-preserve-root /

かかるおろかなる行為の後では、

  • /bin/ls
  • /bin/cat
  • /bin/chmod
  • /usr/bin/file

のような、偉大なるツールのたぐいはみな消え失せてしまった。まだ、ssh接続とbashセッションは生きているはずだ。つまり、bashの組み込みコマンドであるechoとかは残っているということだ。

Bashマクガイバーたれ

root@rmrf:/# ls
-bash: /bin/ls: No such file or directory

lsは存在しないが、echoとfileglobは残っている。どう使えばいいものか。

root@rmrf:/# echo *
dev proc run sys
# echo /dev/pts/*
/dev/pts/0 /dev/pts/3 /dev/pts/ptmx

おや、/dev, /proc, /run, /sysは残ってたぞ。さて、我々はlsを手に入れた。もう少し読みやすくしてみよう。

root@rmrf:/# for file in /dev/pts/*; do echo $file; done
/dev/pts/0
/dev/pts/3
/dev/pts/ptmx

何人かRedditorが、printfも生きているとレスしてくれた。

root@rmrf:/# ls() { printf '%s\n' ${1:+${1%/}/}*; }

「printfは引数がなくなるまでフォーマット文字列を適用しようとする」 -camh-

bashでは関数を定義できるため、いささか制限的ではあるが、lsを作り出すこともできる。

root@rmrf:/# ls() { printf '%s\n' ${1:+${1%/}/}*; }
-bash: syntax error near unexpected token `('

ハァ? 間違いなんてないはずだろ。lsがハッシュされてたりエイリアスされてたりすんのか?

root@rmrf:/# type ls
ls is aliased to `ls --color=auto'

なるほど。つまり、ls--color=auto () { printf '%s\n' ${1:+${1%/}/}*; }と展開されるわけか。やれやれ、まあ、unaliasするか。

root@rmrf:/# unalias ls
root@rmrf:/# ls() { printf '%s\n' ${1:+${1%/}/}*; }
root@rmrf:/# ls
/dev
/proc
/run
/sys
root@rmrf:/# ls /dev
/dev/pts

そしてセーブっと。

root@rmrf:/# echo 'ls() { printf '%s\n' ${1:+${1%/}/}*; }' >> utils.sh
root@rmrf:/# source utils.sh

catはどうだ。組み込みコマンドのreadにパイプとリダイレクトを組み合わせれば、ぎこちないもののcatになる。

root@rmrf:/# (while read line; do echo "$line"; done) < utils.sh
ls() { printf '%s\n' ${1:+${1%/}/}*; }

ここまで揃えれば、echoで任意のバイト列を書き込めることにより、環境を再構築して、curlとかwgetとかで必要なバイナリを引っ張ってこれる。筆者の最初の選択は、他でも言われているようにBusyBoxをゲットすることだ。Busyboxは組み込みLinuxにおけるスイスアーミンーナイフであり、組み込みのwgetやddやtarや、多くの機能がある。Eusebeîa君がこのことについてはよく書いているので、ここでは書かない。

問題はある。

望みのバイト列をechoしてバイナリを作ったとしても、そのファイルには実行権限がない。busyboxを始動させることはできない。この問題に対する最も簡単な対処法としては、なにか実行できるファイルをみつけて、echoで上書きするということだ。しかし、現時点で、/usrと/binはぜんぶ破壊してしまった。そういうわけで、結構めんどくさい。

シェルglobとbashを使って、実行ビットが立っているファイルを探すことができる。ディレクトリはもちろん無視する。

executable () { if [[ ( ! -d $1 ) && -x $1 ]] ; then echo "$1"; fi }

実行可能ファイルを探せ!

root@rmrf:/# for file in /*; do executable $file; done
root@rmrf:/# for file in /*/*; do executable $file; done
root@rmrf:/# for file in /*/*/*; do executable $file; done
/proc/1107/exe
/proc/1136/exe
/proc/1149/exe
/proc/1179/exe
/proc/1215/exe
/proc/1217/exe
/proc/1220/exe
/proc/1221/exe
/proc/1223/exe
/proc/1248/exe
/proc/1277/exe
/proc/1468/exe
/proc/1478/exe
/proc/1625/exe
/proc/1644/exe
/proc/1/exe
/proc/374/exe
/proc/378/exe
/proc/471/exe
/proc/616/exe
/proc/657/exe
/proc/self/exe

やったね。いや、でもまてよ。こいつぁ、もうディスク上には存在しない実行ファイルへのシンボリックリンクじゃねーか。executable()を書き換えて、シンボリックリンクは無視するようにしよう。

root@rmrf:/# executable () { if [[ ( ! -d $1 ) && ( ! -h $1 ) && -x $1 ]] ; then echo "$1"; fi }
root@rmrf:/# for file in /*/*/*; do executable $file; done
root@rmrf:/# for file in /*/*/*/*; do executable $file; done
root@rmrf:/# for file in /*/*/*/*/*; do executable $file; done
root@rmrf:/# for file in /*/*/*/*/*/*; do executable $file; done

さてと、やれやれ。何かカーネルに使えるものがあるかも知れないな。まあ少なくとも、sysrqマジックで再起動はできるわけだ。

root@rmrf:/# echo 1 > /proc/sys/kernel/sysrq
root@rmrf:/# echo "b" > /proc/sysrq-trigger

さて、マシンから完全に締め出しを食らったので、この金曜日は何かもっと別の有意義なことをするとするかな。ご愛読ありがとうございました。筆者のさらなるご活躍にご期待下さい。あと、実行ビットを立てる方法があったら知らせてくれよな。

追記、Redditorのthrow_away5046が、詳細な、美しい、解決方法をレスしてくれた

同じアーキテクチャのぶっ壊してないマシン上で

$ mkdir $(xxd -p -l 16 /dev/urandom)
$ cd $_
$ apt-get download busybox-static
$ dpkg -x *.deb .
$ alias encode='{ tr -d \\n | sed "s#\\(..\\)#\\\\x\\1#g"; echo; }'
$ alias upload='{ xxd -p | encode | nc -q0 -lp 5050; }'
$ upload < bin/busybox

訳注: ncでTCPの5050ポートで待ち受けて、接続してきたリモートホストにbusyboxのバイナリを送りつける

rmrfしたマシン上で

# cd /
# alias decode='while read -ru9 line; do printf "$line"; done'
# alias download='( exec 9<>/dev/tcp/{IP OF NON HOSED BOX}/5050; decode )'
# download > busybox

訳注:pseudo file経由でぶっ壊してないマシンのIPのTCPの5050ポートに接続して、返ってきたbusyboxのバイナリをファイルに書き込む。

busyboxのパーミッションを変更するshared objectを作る

$ cat > setx.c <<EOF
extern int chmod(const char *pathname, unsigned int mode);

int entry(void) {

        return !! chmod("busybox", 0700);
}
char *desc[] = {0};

struct quick_hack {

        char *name; int (*fn)(void); int on;
        char **long_doc, *short_doc, *other;

} setx_struct = { "setx", entry, 1, desc, "chmod 0700 busybox", 0 };
EOF
$ gcc -Wall -Wextra -pedantic -nostdlib -Os -fpic -shared setx.c -o setx
$ upload < setx

訳注:busyboxというファイルの実行ビットを立てるコード(setx)をshared objectとしてコンパイルして、busyboxを送信したのと同様の方法で送信。

setxをenableして、setxを組み込み関数とし、busyboxを実行可能にする

# ( download > setx; enable -f ./setx setx; setx; )
# /busybox mkdir .bin
# /busybox  --install -s .bin
# PATH=/.bin

訳注:GNU bashの組み込みコマンド、enableの-fオプションは、shared objectを読み込んで、ファイル名と同じ組み込みコマンドとして実行できる。
Bash Reference Manual: Bash Builtins

結果

なんともマクガイバー的だ。

2014-06-14

8086のバイナリが汚すぎる

池袋バイナリ勉強会に参加して、8086の逆アセンブラーを作成しようとしているのだが、これが思いの外に難しい。いや、めんどくさい。

筆者は、これまでx86アセンブリには、ニーモニック経由でしか触れてこなかった。movはmovであり、それ以外の何者でもなかった。

mov ax, bx

などと書いたら、これをアセンブラーにビット列に変換させて、その後は何も考えなかった。

既存のバイナリを逆アセンブラーにかけて読む場合でも、やはり逆アセンブラーがバイナリをニーモニックに変換してくれるので、やはりビット列による表現方法に関しては、考えたこともなかった。

さて、池袋バイナリ勉強会に参加したので、この機会に、逆アセンブラーでも実装しようと思い立った。そこで、Intelの当時の8086の資料を読んでみた。

Index of /Intel/x86/808x/datashts/8086

そして、絶望した。8086のビット列は汚い。汚すぎる。我々はこんなに汚いバイナリの上に成り立っていたのかと思うと、愕然とする。

8086のバイナリは、最初の1バイトを読めば命令を判定できる。その後にオペランドが続く。問題は、ニーモニック上からはひとつの命令だと普段我々が認識している命令は、8086バイナリでは、複数のビット列で表現されるのだ。

例えば、8086のバイナリからみると、movというのは、7種類のバイナリ列で表現されている。レジスタ同士、レジスタとメモリのmovや、即値からレジスタやメモリといった操作で、ビット列が違うし、アキュムレーターとかセグメントレジスターといった特別なレジスターを操作するためにも、専用のビット列が用意されている。

MOV亜種 ビット列
Register/Memory to/from Register 100010
Immediate to Register Memory 1100011
Immediate to Register 1011
Memory to Accumulator 1010000
Accumulator to Memory 1010001
Register/Memory to Segment Register 10001110
Segment Register to Register/Memory 10001100

それだけではない。一つのバイナリ列にしても、複雑なビットフラグで、レジスタ間の操作や、あるいはメモリーへの操作であるなどを指定している。しかもそのビットフラグは、命令を表現する1バイトの一部を使っていることもあるのだ。そう、上の表で8bit使っていないのは、単に使われていないだけではない。フラグとして使っているのである。

MOV亜種 ビット列
Register/Memory to/from Register 100010dw
Immediate to Register Memory 1100011w
Immediate to Register 1011w reg
Memory to Accumulator 1010000w
Accumulator to Memory 1010001w
Register/Memory to Segment Register 10001110
Segment Register to Register/Memory 10001100

dは1bitのフラグで、d = 1のとき、レジスターがdestinationであり、d = 0のときは、 レジスターがsourceとなる。つまり、sourceとdestinationを、このフラグによってひっくり返す必要がある。

wは1bitのフラグで、w = 1のとき、命令はワードサイズ(2バイト、16bit)で処理し、w = 0のときは、バイトサイズで処理する。つまり、レジスターやオペランドのサイズを変えなければならない。

regというのは3bitのレジスターを指定する識別番号である。wフラグによって、ワードサイズのレジスター(AX, BXなど)とバイトサイズのレジスター(AL, BLなど)を切り替えなければならない。

また、今回は違うが、regにはセグメントレジスターを指定する2bit版のものもある。

そして、これに続くオペランドがまたひどい。mov以外でもよく使われるオペランドに、

mod reg r/m

というものがある。これは1バイトを、2bit, 3bit, 3bitに区切り、オペランドとして使うレジスターやメモリを指定している。

mod(mode)は2bitのフラグで、オペランドがどのようなものかのモードを指定する。これによって、r/mがレジスターになったりメモリーアドレッシング・モード指定になったりする。

メモリーアドレッシング・モード。これが、厄介だ。

8086では、やたらに複雑なメモリーアドレッシング・モードがある。これでも、まだ少ない方なのだ。8086の系譜は、この後ますますこのアドレッシング・モードを拡張していったのだ。とにかく、アドレッシング・モードとは、単にメモリを指し示すアドレスをそのまま用いるのではなく、SI + アドレスとか、DI + アドレスとか、BX + SI + アドレスとか、とにかくやたらに組み合わせがある。

このアドレスを、Intelの仕様書ではdisp(displacement)と書いている。

dispというのは基本的にバイトサイズだ。mod = 00のときは、dispは存在しない。ところが、である。mod = 00かつr/m = 110のときのみ、dispはワードサイズとなり、アドレッシング・モードはdispのみとなるのだ。ひどい例外的ルールもあったものだ。

さて、ビット列の文法はだいたい理解した。しかし、これはいったいどうすればいいのだろうか。どう考えても汚いコードしか思い浮かばない。どうせたかだか1バイトで命令を判定できるのだから、256個の配列や256個のswtich caseを書くのが一番手っ取り早いのだろうか。しかし、命令にもフラグが入っている都合上、極めて汚いコードになってしまう。

そして、オペランドのmod reg r/mだ。めんどくさい。極めてめんどくさい。

とりあえず書こうと思っては、思い直して止まっている。ビット列に対してこのようなパースを簡単にできるライブラリや言語機能が欲しい。

ドワンゴ広告

この記事はドワンゴの勤務時間を極端に減らして捻出した余裕で休日に池袋バイナリ勉強会に参加して書いた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-06-11

興味深い記事

systemcall dot org » Trashing Chromebooks

ARM環境における自由ソフトウェアの開発組織であるLinaroでは、LinuxカーネルやGCCやLLVMやbinutilsなどの様々なツールチェインを、ARM環境でビルドしてテストしている。

問題は、そのビルドとテストを実機で行うARM環境に、あまりいい候補がないということだ。

テストは高速で行われて欲しい。また、テストは常に行われるので、テスト環境は常に酷使される。

問題は、ARMでは、そのようなテストに適したコンピューターが存在しないということだ。

いくつかの開発ボードを試してみたものの、性能が悪すぎたり、不安定すぎたりしたそうだ。

不安定というのは、連続稼働していると、ビルドが何の理由もなく失敗するそうだ。失敗した原因のファイルもまちまちで、明らかにハードウェアの問題であるという。

結局Linaroのテスト環境は何になったかというと、なんと、Samsung Chromebookだという。Chromebookは、自動化されたテスト環境としてのbuildbotとしては甚だ不適当である。たとえば、電源を手動で入れなければならないなどの不都合がある。それを考慮しても、不安定すぎる開発ボードよりマシなのだという。

参照元では、この手の開発ボードは、コンピューター全体のテストを十分に行っていないのではないかと推測している。Chromebookは製品であり、野に解き放たれて、過酷な環境で使われる。そのため、コンピューター全体を長期間酷使するテストもする。一方、開発ボードは、それほど本格的なテストをしていないのではないかとしている。

参照元が推測している、不安定の理由としては、熱だ。なるほど、ARMのプロセッサーは、保証されている動作温度の範囲内ではあるが、基板のその他の部品が怪しいとしている。特に怪しいのはSDカードリーダーだそうだ。温度が上がると不安定になる。開発ボードにはUSBポートもついているが、ブートはSDカードからしか出来ず、使わざるを得ないのだそうだ。

参照元では、Chromebookをbuildbotにする手順を説明している。

開発モードを有効にしてGNU/Linuxをインストールし、ハードウェアも分解してバッテリーを取り外したChromebookは、極めて安定して動作するそうである。唯一の欠点は、一部完全なリモートでの作業が出来ないことだという。

The Great C Runtime (CRT) Refactoring - Visual C++ Team Blog - Site Home - MSDN Blogs

MicrosoftのCRTが如何にクソであるかという告白記事。

従来、MSVCのバージョンごとに別のCRTライブラリを出してきたが、これは極めて利用者にとっても開発者にとっても面倒なので、今後はMSVCのバージョンごとにライブラリまで分断するようなことをやめて、互換性を保ちつつ更新していくという。

また、MSVCのCRTは1980年代から続く汚いコードで、当時としては理由があったが、今となってはむしろコンパイラーによる最適化の妨げとなる汚いハックが満載で、#ifdefだらけであり、悲惨なことになっているので、大掛かりなリファクタリングを行ったとのこと。

特に、中身をC++で書きなおして、まともなコードにしたそうだ。

まあ、MSVCは遠からず滅びるコンパイラーであるのだが。

[Phoronix] Rich Geldreich Leaves Valves; Points To More "End Of OpenGL" Articles

本の虫: OpenGLでムカつくこと本の虫: OpenGLドライバー品質の実情で翻訳もした、OpenGLに吠えていたRich Geldreichが、Valveをやめたそうだ。Geldreichは、ValveでvoglというOpenGLのデバッグ用のツールを開発していた。

Red Hat | Red Hat Unveils Red Hat Enterprise Linux 7, Redefining the Enterprise Operating System

RHEL 7が正式にリリースされたようだ。興味深いことに、デフォルトのファイルシステムがEXT4ではなくXFSになっている。

ドワンゴ広告

この記事は、N3980を読むのに疲れたので、気晴らしにドワンゴ勤務中に書いた。

ところで、最近のドワンゴ社内では、God's Gambitというゲームが流行っている。これはUNOに似たゲームではあるが、カードを出す代わりに、自分の場に出して、特殊効果を使うこともできるゲームだ。ただし、自分の場に出すとカルマがたまるので、どんどん罪深くなっていく。このゲームはとても面白いので、一般の店頭に並んだら是非とも買いたい。

それはさておき、筆者がよくたずねられる質問に、「C++はドワンゴ社内でどこに使われているのか」というものがある。これについて調べたところ、コメントサーバー、動画、生放送の配信システム、検索エンジン、レコメンドエンジン、等に使われているそうだ。

そういえば、筆者の周りには、ErlangやH.264/HEVC関連の参考書が目立つ。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-06-09

2014-05 pre Rapperswil mailingのレビュー: N3967-N3979

2014-05 pre Rapperswil mailingが公開された。ざっとタイトルを眺めると、今回も面白そうな論文がちらほらある。早速レビューしていこう。

N3967: C++ Standard Library Active Issues List
N3968: C++ Standard Library Defect Report List
N3969: C++ Standard Library Closed Issues List

標準ライブラリに存在が認知されている既存の問題集、修正済みの問題集、議論の結果実は問題ではなかったとされた問題集。

N3970: Technical Specification for C++ Extensions for Concurrency, Working Draft

新しい並列実行ライブラリを含むConcurrencyのTechnical Specification。歴史的にTSとして出た機能が、そのまま標準規格に入ることはないが、これを叩き台に、将来の規格入りを目指して、今後も並列実行ライブラリが議論されるだろう。内容としては、スレッドよりも高級な並列実行ライブラリである、ExecutorとShcedulerと、std::futureにis_readyとかthenとかwhen_allなどの便利なメンバー関数を追加する文面が入っている。

N3971: Concurrency TS Editor's Report, February 2014

今回のConcurrency TSに加えられた変更に対する、TS編集者の報告書。

[嫌気のするPDF] N3972: Source-Code Information Capture

リフレクションのひとつとして、ソースコード情報取得ライブラリの提案。

C++では、__LINE__とか__FILE__とか__func__といったCプリプロセッサーマクロにより、ソースコードファイルのその文脈における行番号とかファイル名とか関数名を取得することができる。

しかし、Cプリプロセッサーは醜悪である。筆者はその臭いに耐えられぬ。このような情報は、もっとまともな方法で取得できるべきだ。

そういうわけで、C++17向けに議論されているリフレクション機能のひとつとして、ソースコード情報取得ライブラリが提案されている。

N3972提案の設計では、source_context型のオブジェクトは、構築された文脈におけるソースコード情報を保持するのだそうだ。

// N3972提案
int main()
{
    std::source_context sc ;

    std::cout
        << u8"行番号: "  << sc.line_number() << '\n'
        << u8"行頭からの文字数: " << sc.column() << '\n'
        << u8"ファイル名: " << sc.file_name() << '\n'
        << u8"関数名: " << sc.function_name() << '\n' ; 
}

この情報が、どのような文字列で表現されるかは、実装定義(implementation-defined)である。

また、この提案は興味深いことに、source_contextをデフォルト実引数で初期化した場合や、クラスのデータメンバーとして初期化した場合に、その構築を呼び出した文脈の情報をキャプチャすると書いてある。つまり、以下のようになる。

// N3972提案
void f( std::source_context a = std::source_context() )
{
    std::cource_context b ; // bはこの場所の情報を補足する
}

void g()
{
    f() ; // aはこの場所の情報を補足する

    std::source_context c ;
    f( c ) ; // aはcのコピー
}

struct S
{
    S() { }
    S( std::source_context ) : d(sc) { }
    std::source_context d ;
} ;

void h()
{
    S s1 ; // s1.dはこの場所の情報を補足する

    std::source_context e ;
    S s2(e) ; // s2.dはeのコピー
}

デフォルト実引数がどの文脈で評価されるかということについて、規格上の定義はないし、今後も規定するかどうかはわからないが、source_contextの構築においては、そのように規定するということだ。

なぜ、デフォルト実引数やデータメンバーの構築について、わざわざ規定するかというと、これを使って、ロギングライブラリなどを実装できるようにするためだ。

論文で、議論で要望が高かったものの、今回の提案には含めなかった機能に、比較関数とstd::hashがある。これは、set/map/unordered_set/unordered_mapのようなコンテナーにstd::source_contextを格納する際に必要になる。そのような需要は当然あるだろう。問題は、いったいどうやってファイル名や関数名といった情報を比較すればいいのだろうか。いったい何が「等しい」のだろうか。簡単に意見の一致は見られないだろう。このことはもっと議論されるべきであるので、今回の提案には、比較関数やハッシュ関数は定義されていない。

他にも要望が高かった機能としては、ソースファイル先頭からの文字数を取得する方法がある。これは、コンパイラー実装の都合上、どの程度困難であるのかを見極めるために、今回の提案には含まれていない。

function_nameは、コンパイラー向けの関数名と、開発者向けの関数名の二つに分割すべきだという要望もあった。これは、「コンパイラー向け」とか「開発者向け」というものの定義が出来ない時、ひどく実装定義な機能であるとして、この提案には含めなかったそうだ。

これは泥臭い機能である。しかし、現実に必要とされている機能であることは確かだ。Cプリプロセッサーマクロよりもまともな方法であるので、筆者はこの提案を気に入っている。ただし、もっと議論が必要だろう。

ちなみに、std::source_contextのコンストラクターとメンバー関数はconstexprであるので、中3女子も一安心していることだろう。

[吐き気のするPDF] N3973: A Proposal to Add a Logical Const Wrapper to the Standard Library Technical Report

論理的なconst性を伝播させるのライブラリ、logical_constの提案

論理的なconst性は、クラスのメンバーを超えて受け継がれない。論文筆者によると、以下のコードは、経験あるC++erも驚くという。

// 驚くか?
struct A
{
    void bar() const
    {
        std::cout << "bar (const)" << std::endl;
    }

    void bar()
    {
        std::cout << "bar (non-const)" << std::endl;
    }
};
struct B
{
    B() : m_ptrA(std::make_unique<A>()) {}
    void foo() const
    {
        std::cout << "foo (const)" << std::endl;
        m_ptrA->bar();
    }

    void foo()
    {
        std::cout << "foo (non-const)" << std::endl;
        m_ptrA->bar();
    }

    std::unique_ptr<A> m_ptrA;
};

int main()
{
    B b;
    b.foo();
    const B const_b;
    const_b.foo();
}

実行結果は以下の通り。

foo (non-const)
bar (non-const)
foo (const)
bar (non-const)

筆者は、この挙動に驚かないし、むしろこの挙動以外であれば驚くのだが、どうやら、論文筆者によれば、この挙動は驚きらしい。たとえクラスのオブジェクトはconstであったとしても、データメンバーのポインター型はconstでない以上、何が驚きなのかわからない。

ただし、constメンバー関数を呼び出すのに、いちいち型キャストをするのは面倒だ。論文筆者は、const性を伝播させるために、->などの演算子をオーバーロードして、const版のポインターを経由して呼び出すというクラスを標準ライブラリに提案している。


struct B
{
    B();               // unchanged
    void foo() const;   // unchanged
    void foo();         // unchanged

    std::logical_const<std::unique_ptr<A>> m_ptrA;
};

これによって、const版のメンバー関数がよばれるようになり、実行結果も、以下のようになる。

foo (non-const)
bar (non-const)
foo (const)
bar (const)

constではないポインターを取り出す、cast_away_logical_constメンバー関数も用意されている。長ったらしい名前なのは、コードレビューでの発見を容易にするためだという。

まあ、あっても困らないライブラリではある。

[めまいのするPDF] N3974: Polymorphic Deleter for Unique Pointers

ゼロ原則と、ゼロ原則をサポートするためのunique_ptr拡張案。

かつて、C++には三原則があった。三原則、すなわち、コピーコンストラクター、コピー代入演算子、デストラクターのうち、どれかひとつでもユーザー提供されたのならば、残りの二つも、おそらくユーザー提供する必要があるだろうという原則である。

C++にムーブセマンティクスが導入されてから、これは五原則に変わった。三原則に加えて、ムーブコンストラクターとムーブ代入演算子が加わった。

五原則は、すでに一年前のことだ。2013-03-15のN3578で提唱されて、2014-01-01のN3839でも改定されている。

今回は、それとは別に論文著者でもあるPeter Sommerladが提唱したゼロ原則の話だ。

ゼロ原則、すなわち、何もユーザー提供する必要なないのならば、コンパイラーの生成したデフォルトのコンストラクター、代入演算子、デストラクターが動くべきという原則だ。

しかし、既存の多くのC++教科書では、このゼロ原則に反することを教えている。virtualデストラクターだ。

デストラクターがvirtualでなければ、基本クラス経由でデストラクターを呼び出した時に、正しい実行時の型のデストラクターが呼ばれない。

struct Base { } ;

struct Derived : Base
{
    Derived()
    { std::cout << "constructed" << '\n' ; }
    ~Derived()
    { std::cout << "destructed" << '\n' ; }    
} ;
    

int main( int argc, char ** argv  )
{
    std::unique_ptr<Base> p = std::make_unique<Derived>() ;
}

実行結果は、以下のようになる。

constructed

なんと、デストラクターが呼び出されていない。これは、デストラクターがvirtual関数でないためである。

ためしにvirtualを付けてみよう。


struct Base
{
    virtual ~Base() { }
} ;

こうすると、デストラクターが呼ばれる。デストラクターがvirtual関数となったので、実行時の型に応じて、基本クラスのポインターやリファレンスを経由しても、正しくデストラクターが呼ばれるようになる。

このため、既存のC++教科書は、派生する場合はかならず基本クラスのデストラクターを、たとえ空であっても、virtual関数にしようと推奨している。そのようなボイラープレートコードを自動生成するするIDEまである。

しかし、これはおかしくないだろうか。デストラクターで何もする必要がなければ、なぜわざわざ書く必要があるのだろうか。デフォルトは適切に動くべきである。

じつは、shared_ptrを使えば、デリーターがポリモーフィックに振る舞うために、非virtualデストラクターでも実行時にポリモーフィックに呼び出されてくれるのだ。


std::shared_ptr<Base> ptr = std::make_shared<Derived>() ;

しかし、shared_ptrはリファレンスカウントというコストがかかる。リファレンスカウントが必要ない場合、これはコストである。

一方、そのようなコストのかからないunique_ptrのデリーターは、ポリモーフィックではない。ポリモーフィックなデリーターはコストがかかるので、unique_ptrではデフォルトではないのは当然だ。しかし、ゼロ原則のためには、ポリモーフィックなunique_ptr用のデリーターが欲しい。そこで、そのようなデリーターの提案。

デリーター、safe_deleteは、基本クラスのデストラクターがvirtualでなくても、派生クラスのunique_ptrから基本クラスのunique_ptrに変換された場合に、実行時の型にしたがって、正しくデストラクターを呼び出してくれる。

// N3974提案
struct Base { } ;
struct Derived : Base
{
    ~Derived() { } 
} ;

int main()
{
    std::unique_safe_ptr<Base> ptr = std::make_unique_safe<Derived>() ;

    // Derived::~Derivedが呼ばれる
}

unique_safe_ptr、make_safe_ptrは、safe_deleteがデフォルトになったテンプレートエイリアスである。


template < typename T >
unique_safe_ptr = unique_ptr< T, safe_delete > ;

template <typename T, typename... Args >
unique_safe_ptr<T> make_unique_safe( Args && ... args ) ;

実は、もうひとつ、checked_deleteというデリーターも入っている。これは、基本クラスのデストラクターがvirtualではない場合に、ill-formed、つまりコンパイルエラーになるデリーターだ。ill-formedとならない場合は、従来のデリーターであるdefault_deleteと同じ挙動になる。

 // N3974提案
struct B1 { } ;
struct D1 : B1 { } ;

struct B2 { virtual ~B2 { } } ;
struct D2 : B2 { } ;

int main()
{
    // ill-formed
    std::unique_checked_ptr<B1> ptr = std::make_unique_checked<D1>() ; 

    // well-formed
    std::unique_checked_ptr<B2> ptr = std::make_unique_checked<D2>() ; 
}

論文には、リファレンス実装も含まれている。

N3975: URI - Proposed Wording (Revision 5)

URIライブラリの文面案。この提案は標準規格ではなく、TSとして発行されることを目指している。

N3976: Multidimensional bounds, index and array_view, revision 2

連続したストレージを、あたかも多次元配列であるかのように見せかけて操作できるarray_viewライブラリの文面案。

// N3976提案
int main()
{
    std::vector<float> v( 32 * 32 ) ;
    auto view = std::array_view< float, 2 >{ { 32, 32}, v } ;

    // std::index<2>
    for ( auto idx : view.bounds() )
    {
        view[ idx ] ; // アクセス
    }
}

[再開すべきではないPDF] N3977: Resumable Functions

中断可能関数(resumable function)の文面案。これは標準規格ではなく、TSとして発行されることを目指している。

文法を簡単に解説すると、中断可能関数をresumableキーワードで宣言し、途中で処理を返したいところで、awaitキーワードを使う。中断可能関数は、戻り値の型にfuture<T>かshared_future<T>を返さなければならない。中断可能関数の呼び出し元が、戻り値のfutureのオブジェクトにセットされた値を取り出そうとすると、中断可能関数の実行が再開される。

// N3977提案
// 時間のかかる処理
int slow() ;

std::future<int> f() resumable
{
    // 実行中断されて呼び出し元に帰るかも
    auto result = await slow() ;
    return result ;
}

void g()
{
    auto f = f() ; // 実行中断されているかも
    auto value = f.get() ; // 実行再開するかも
}

N3978: C++ Ostream Buffers

マルチスレッドからのストリーム出力で、結果を保証するためのバッファーの提案。規格上、ストリーム出力は競合しないことは保証されているが、その出力については保証されていない。そのため、複数のスレッドから同時に出力する場合でも、出力が細切れにならないことを保証するバッファーライブラリを提案している。

// N3978提案
void f()
{

    {
        std::ostream_buffer buf( std::cout ) ;
        buf << "hello, " << "world!" << std::endl ;
    } // bufが破棄されるタイミングで一気に出力される

}

ostream_bufferは、自動ストレージ上に構築して使う。通常のストリームのように使うとバッファーされ、、オブジェクトが破棄されるタイミングで、一気に競合せずに出力される。

[予定にないPDF] N3979: AGENDA, PL22.16 Meeting No. 63, WG21 Meeting No. 58, June 16-21, 2014 -- Rapperswil, Switzerland

スイスのRapperswilで6月16日から21日にかけて開催される国際会議の予定表。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

C++WG論文集が出たので、ようやく、ドワンゴ社内で仕事をしているふりができるようになった。いや、正確にはこれも仕事ではないのだが。

今回は最初からTS発行を目指す提案が多い。これは、実用化されるまであと10年ないし20年はかかることを意味している。ドワンゴ社内で論文の概要を紹介すると興味を示すC++エンジニアはいるが、残念ながら、近い将来に使えるようにはならない機能だ。まだまだ議論と設計が必要なのだ。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

シニアエンジニアによるガラケー大戦回顧録に参加した

シニアエンジニアによるガラケー大戦回顧録 : ATNDに参加した。

この会合の主旨としては、当時の邪悪で不自由極まりないガラケーの開発姿勢が、如何に悲惨で惨めで肥溜めの中の蛭のようなものだったかを、非公開の会合で語ろうというものだ

ガラケーの開発では、技術的に誤っている手法が実に多く使われていた。なるほど、不自由で貧弱なガラケーの実装が規格準拠しておらずバグだらけだったこともあろう。それにしても、ガラケーとは関係がないサーバーの中だけで完結する場所におけるクソもあった。何故そんなことになってしまったのか。

理由は、情報が公に出せず、したがって共有されなかったことだ。情報が共有されないため、表立って議論や相談が出来ない。その状態でかろうじて見つけたちっぽけな情報を元に、技術的に極めて劣っていながらも、何とか動くものを作り出していた。そして、その動くものを、正しいやり方だと勘違いしていたのだ。

なぜそんな馬鹿げた自体を引き起こしたのか。なぜ情報が表に出せなかったのか。

NDA(Non-Disclosure Agreement)である。ガラケー各社は、開発者に対して極めて厳しい、マヌケなNDAを強いていた。そのNDAの強烈なことには、当時のガラケー開発者をして、「今のiPhoneのNDAなんてなきに等しい」と言わしめるほどであったそうだ。

NDAがあるための情報を表に出せない。情報を共有できない。表立って技術を議論できない。しかし、我々は表に出ている情報からしか学べない。

その結果起こったのが、あのガラケーの惨事だ。バッドノウハウをノウハウだと勘違いして、クソみたいな実装のガラケー向けサービスを乱立させ、黒船たるiPhoneやAndroid上陸で沈んでいったガラケー開発会社だ。

その当時、ke-tai.orgを運営していたketaiorg(松井 健太郎) (ketaiorg)氏も、会合に参加していた。氏が自分がke-tai.orgを運営していたと発言すると、その場にいた元ガラケーエンジニア達は、一斉に市の方に向き直って頭を下げた。これはいったいどういうことか。

ke-tai.orgは、NDAに縛られて情報の共有も技術の議論もない暗黒のガラケー開発時代に、様々なガラケーの情報をまとめて掲載していたWebサイトであった。当時のガラケー開発者で、ke-tai.orgのお世話にならなかったものはないほどであったという。

ke-tai.orgで提供していた、ガラケーの全機種の型番リストといった、筆者としては実につまらないように思える情報ですら、極めて貴重でありがたいものであったと、会合の参加者は口々に語った。何でも、そのような情報は、当時何十万円も出さなければ購入できないものであったという。

なぜ、氏はke-tai.orgを運営できたのか。どうやら、氏は当時フリーランスとして働いていて、NDAを結ばなければならない部分とは、直接関わっていなかったのだという。

結局、真にエンジニアに役立つのは、このような公の情報だ。表に出ている情報だ。NDAを結んで得られるクソの搾りカスのようなドキュメントが、サポートが(もしあればの話だが)、いったい何の役に立ったというのか。必要なのは公に情報を出せることだ。知識を共有し、議論できることだ。それができないものに、それを邪悪にも制限するものに、将来はない!

筆者これを聞く。今の世の中に、未だにガラケー時代と変わらぬ鼻クソのようなNDAを結ばなければ、どんなプログラミング言語を使っているかすらわからないようなチンカスプラットフォームがあるという。どこのアホタレとは言わないが、早く行いを改めることを勧める。さもなくば、ガラケーと同じ道をたどるであろう。完全に自業自得であり、筆者は別にカワイソーとは思わん。

当日のガラケーエンジニア達の間でも答えの出ない疑問がある。なぜそんなクソのようなガラケー業界が当時やっていけたのか。この疑問には答えることができる。「金になったから」だ。では、何故金になったのか。この疑問にも答えることができる。「ガラケー利用者が金を出したから」だ。なぜ金を出したのか。これには、参加者一同首をひねるばかりで、誰一人として答えを出せなかった。

当日、会合で出た話は、なかなか公に出せない話ばかりであった。また、筆者としても、記録を取っていないので、詳細を思い出すことはできない。しかし、この話は埋もれさせてはならない。過去の過ちは、公にして、再び同じ轍を踏ませない戒めとしなければならない。そのためにはどうすればいいのか。このような話を持っている人は多いが、なかなか公に話してはくれまい。

思うに、もっと大きな勉強会を開くというのはどうか。100人規模の勉強会を開催すれば、その規模であれば話してもいいと表に現れる元ガラケーエンジニアもいるのではないか。しかし、100人規模の勉強会というのは、甚だ大規模である。100人入れる部屋を確保し、プロジェクターや電源やWiFiを完備した上で、できればインターネット上に動画のストリーミング配信をする機材も欲しい。ああ、そんな都合のいい部屋がどこかにあればいいのだが。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

ところで、歌舞伎座タワーに入っているドワンゴは、108人入れるセミナールームを持っていて、勉強会を積極的に開催している。筆者も、これからはC++の勉強会を積極的に開催しようと思う。そのはじめに、まず6月28日に勉強会を開催する。

本の虫: ドワンゴC++勉強会 #1の開催告知

ドワンゴC++勉強会 #1 - connpass

残念ながら、現時点で定員を上回る応募がされている。C++勉強会の需要はあるようなので、今後も積極的に開催していきたい。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-06-07

もしlambda式がconstexprだったら

lambda式がconstexprでない理由、いや、より正確には、クロージャーオブジェクトの変換関数がconstexpr関数ではない理由。

もし、constexprの場合は、SFINAEの文脈で使えてしまうからだ。lambda式の本体には任意の文を書けるので、以下のような記述が可能だ。

template < typename T,
    void (*)() = [](){
// write whatever expressions that depends on T.
// if any expression is ill-formed for T, substitution fails.
}
>
void f( T ) ;

C++11の規格策定の最終段階で、クロージャーオブジェクトの関数ポインターへの変換関数をconstexprにしようという議論がでたが、当時、筆者はこのコードを示して、SFINAEの文脈で悪用可能であると示し、もって変換関数をconstexpr関数にするのを差し止めた。

これはノドから手が出るほど欲しい魅力的な悪用方法ではあるが、このような機能は、コンセプトのようなもっと洗練された言語機能で解決すべき問題だ。

2014-06-06

ドワンゴC++勉強会 #1の開催告知

connpass: ドワンゴC++勉強会 #1

ドワンゴが入っている歌舞伎座タワーの、ドワンゴの入っている14階のセミナールームで、C++の勉強会、すなわちドワンゴC++勉強会を開催する。

詳細と参加登録はconnpass.comの告知をみてもらうとして、今回は6月28日土曜日の昼に行うので、参加しやすいはずだ。

この勉強会には、C++界隈で有名な、でちまるさん(実際かわいい) (@decimalbloat)氏、狂える中3女子ボレロ村上/陶芸C++er (@bolero_MURAKAMI)氏を招き、Cプリプロセッサーメタプログラミングと、コンパイル時メタプログラミングについて話してもらう。

筆者はこの機会に、去年、ドワンゴ社内の講習会で使ったスライド資料、C++の歴史を、加筆して発表する。

また、今回の勉強会では、LT発表を5人ほど募集している。一人10分の時間を確保した。何かC++について発表したいものは、ぜひともLT枠に応募してもらいたい。勉強会で発表するのは、事前の調査により、必ず勉強になるはずだ。

ドワンゴに入社してよりこのかた、歌舞伎座タワーのセミナールームを使って勉強会を開いて欲しいと、社内からも社外からも言われていた。私は複数のことに並行して集中できないので、入社当初は、溜まっていた論文のレビューと、東京での生活を整える作業に追われていたが、ようやく今の生活も落ち着いてきたので、これからは積極的に勉強会を開催していきたい。

connpass: ドワンゴC++勉強会 #1

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

ドワンゴC++勉強会はドワンゴのリソースを遠慮なく使って開催される。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

ask.fmを始めた

ask.fmで江添に質問

ask.fmを始めた。当分の間、どんな質問にも答える。

昨年まで、筆者は9年間ほど引きこもってC++の規格を学んでいた。世間との交わりを断つということは、物事に集中できる環境ではある。筆者は社交性に優れているわけではないが、決して社交性のない人間ではない。ただ、これまでは社交性が必要ではなかったし、また勉強の妨げにもなったので、あえて用いていなかった。

さて、今の仕事であるC++の啓蒙や、ドワンゴの宣伝は、表に出なければならない仕事である。社交性が必要とされる。筆者は必要なことは行う人間である。そのため、東京に出てきてから、色々と表に出てきているが、どこに行っても、「まさか江添が表に出てくるとは」などと言われる。

これは、畢竟、京都という地方に住んでいたことと、表に出ていなかったことが原因である。C++を深く学ぶには都合がよかったが、今の仕事である、C++の啓蒙やドワンゴの宣伝をするにあたっては、現状は問題だ。この問題は解決する必要がある。私に質問しやすい雰囲気を作らねばならない。

問題は、質問というものは、直接行うには勇気がいるものである。そこで、今回はask.fmを使い、匿名での質問を受け付けることにした。また、どんな質問にも答えることにした。

ask.fmで江添に質問

2014-06-05

freeeの会社見学に行ってきた

freeeの会社見学に行ってきた。

freeeというのは、Web上で会計がつけられるSaaSSを提供している会社だ。ちなみに、社名はtypoではない。eは3個連続している。

職場はいかにも急成長の企業らしい楽しそうな配置がなされていた。ミニ四駆のコースが設置されていたり、壁にホワイトボードの塗料を塗って即席ホワイトボードにしていたりしていた。せっかくなので、「ドワンゴは本物のC++プログラマーを求めています」と落書きしてきた。残念ながら、その壁にはすでにQiitaの落書きがされていたので、一番乗りはかなわなかった。それにしても、実にシュールな光景であった。

色々と話をしたが、どうやら今のところ、freeeではC++は使われていないらしい。

freeeのTシャツをもらった筆者は、freeeを後にして帰路についた。ドワンゴにもあらゆる文脈で使えるTシャツが欲しいものだ。超会議3のスタッフTシャツも、前は悪くないのだが、後ろに運営と大きく描かれていて、文脈によっては誤解を受けるので使いにくい。そう、大昔のGet Realという文字の下に目玉のついた手が描かれているようなシャツが欲しい。

さて、今週はいろいろあって、なかなかC++の論文のレビューがはかどらなかった。

ドワンゴ広告

この記事はドワンゴを早めに退社してから会社見学に行った後、自宅で書いた。

論文のレビューがはかどらない原因として、ドワンゴ社内にボードゲームやら猫画像やらの誘惑が多すぎることも挙げられる。特に甚だしきは、筆者の入っているIRCチャンネルに同僚が猫画像を無差別爆撃するBOTを投入するなどの陰湿極まりない嫌がらせを受けていることだ。じつにありがたいやけしからんことである。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

connpassのHTML編集がクソすぎる

とある理由で、connpass.comでHTML編集を行ったが、これがクソすぎる。

まず、connpassはHTMLしか編集できない。CSSを記述することは出来ない。したがって、fontのようなクソみたいなタグが乱立する。font要素は、HTML5では廃止されている要素である。にわかに1990年代のインターネットに戻ってしまった。

しかし、HTML5では、style要素にscoped attributeをつけることで、style要素の任意のflow contentの先頭に書くことができるのだ。

<div>
<style scoped="scoped">
p { color : red ;}
</style>

<p>
This is red.
</p>
</div>

<p>
This is probably not red.
</p>

まだHTML5がwhatwgによって策定されていた当時は、scoped styleをサポートしているブラウザーはなかったので諦めていたが、今試した所、どうやらFirefoxもChromiumもサポートしている。使える。遠慮する必要はない。

喜び勇んでscoped styleをconnpassで使おうとしたが、connpassのHTML編集は、勝手にstyleタグを削除する。

それどころではない、style attributeも削除されるし、section要素も削除される。何なのだこれは。connpassは1990年台のインターネットを再現したいのか? どこまでクソに落ちれば気がすむのだ。

色々と考えた挙句、筆者はマークアップの綺麗さを重視した。

さて、何故筆者はconnpassでHTML編集をしているのか。その謎は明日明かされる予定だ。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

そういえば、この記事とは何の関係もないが、筆者は6月21日の歌舞伎座.tech#4「コンピュータ将棋プログラミング」は聞きに行く予定だ。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-06-03

Appleが新言語、Swiftを発表するも、すでに閉鎖的すぎて絶望しかない

Objective-Cという汚らしい言語を長年強制し、プログラマーを絶望の淵に叩き込んでいたAppleが、とうとう新言語を発表した。名前はSwiftという。

iTunes - Books - The Swift Programming Language by Apple Inc.

ただし、現時点で、Swift言語仕様書のダウンロードと閲覧に、Appleの独自仕様満載の不自由なデバイス、の上で動く不自由なOS、の上で動く不自由な閲覧ソフトウェアが必要だ。そのため、筆者は未だに言語仕様書を読めずにいる。これをもってこれをみると、Appleの新言語にかける姿勢が如実に現れていると言えよう。すなわち、Appleの不自由なシステム以外は、市場として考慮する必要がないということに違いない。事実、Objective-Cは、Appleの不自由なシステムでプログラミングするにあたって、仕方なく使わなければならないものである。Swiftも同じ道をたどるだろう。

まだ我々の記憶に残る、例のカリスマ男が故人となった今、邪悪で不自由なシステムとプログラミング言語を世界に蔓延させるAppleは、早くその市場シェアを自由でまともなOSと言語に奪われてほしいものだ。

D, Go, Rust, Valaと、最近、新しい言語の登場が相次いでいるが、果たしてC++を置き換えるものがでるであろうか。

追記:Appleの公式Webサイト上から読める仕様書を発見した

The Swift Programming Language: About Swift

2014-06-01

池袋バイナリ勉強会に行ってきた

「kernelvmの発表者に、プログラミングを学んでわずか半年にして、PDP-11エミュレーターを実装した強者がいる」

kernelvmに参加した南山まさかず君は筆者に言った。なんと、プログラミング初心者が半年でPDP-11エミュレーターを実装し得ただと? いったい我々は何をやっていたのだ。その強者と話がしてみたい。きっとまだプログラミングの基礎を覚える過程を記憶していて、プログラミングを学ぶ方法がわからない筆者として、興味深い話が聞けることであろうし、半年でPDP-11エミュレーターを実装できたのであれば、本物のプログラマーの素質を持っているであろうから。

聞けば、その強者は、七誌氏の主催する、池袋バイナリ勉強会なる勉強会で学んだという。一体どのような勉強会なのだろうか。ひとまず、その勉強会に参加してみよう。幸い、今週の土日に、初心者向けの講座が開かれる。

池袋バイナリ勉強会の会場は、東京都豊島区池袋 2-12-11 三共池袋ビルであった。Google Mapsで確認したところ、池袋駅からそれほど迷わずに行けるように思われた。当日、筆者は悠々と洗濯をし、弁当を作り、会場に向かった。

ところが、現地は思いの外に入り組んでおり、30分以上迷った末に、ようやく、数時間単位で部屋を貸す変わったホテルに囲まれた会場を発見した。

中に入ると、ちょうど、勉強のための環境を構築中であった。

環境構築

なんと、七誌氏はこの勉強会のために、8086向けのUNIX v6とそのコンパイラー、インタプリターを用意したのだという。しかも、導入は以下のように、とても簡単だ。

$ hg clone https://bitbucket.org/7shi/i8086tools
$ cd i8086tools
$ make
$ sudo make install

筆者は事前に何も準備をしてこなかったので、まずMercurialをインストールした。

sudo apt-get install mercurial

そして、インストールしたものをパッケージ管理したかったので、checkinstallを使おうとしたが、なんと、今使っているラップトップには、checkinstallが入っていなかったので、それもいれた。そういえば、最近Ubuntuでパッケージ化されているClangも、なかなか使えるようになってきたので、もう独自ビルドしていないのであった。

実に、GNU/Linuxの有名なディストロは、筆者のような情弱にも優しいOSであると言える。筆者は遅刻をしたものの、即座に環境を構築することが出来た。

勉強会の参加者の多くは、不自由なWindowsや不自由なMacを使っていたが、極めて苦労していた。午前中は環境構築だけで潰れたようだ。

しかし、不自由なWindows上でこの環境構築をするというのは、極めて不思議な状況だ。まず、不自由なWindowsで、UNIXの極めて薄いレイヤーである自由なMinGWを動かし、その上に8086インタプリターやUNIX v6を動かすのであるから、レイヤーにレイヤーを重ねた環境である。なぜGNU/Linuxを使わないのか理解に苦しむ。

そして、この環境は、なかなか素晴らしい。思えば、今の環境は、バイナリの入門用には、複雑になりすぎた。PEフォーマットやELFフォーマットをパースするのは一苦労だし、x64は相当に複雑になった。この環境は、a.outフォーマットなので、16バイトのヘッダーとtextセクションとdataセクションだけという、実に単純な構成だ。

さて、ひと通り環境を理解した筆者は、8086の逆アセンブラを実装しようとした。それには、まずIntelの資料を理解しなければならない。さっそく資料の読解にとりかかった筆者であったが、8086のバイナリは、想像を絶するほどに汚かった。

筆者は、x86アセンブリはある程度経験している。そのため、8086のバイナリの理解は、それほど苦労しないであろうとたかをくくっていた。ところが、である。8086のバイナリは、想像をはるかに上回る汚さであった。

これまで、筆者は、x86は、アセンブラー、逆アセンブラーが提供する、親切なニーモニック経由でしか触れていなかった。MOVはMOVであって、それより先を考える必要はなかった。

ところが、である。Intelの資料による8086のビット列を参照すると、MOVはてんでばらばらな複数のビット列から成り立っていることがわかった。しかも、オペランドの組み合わせにより、ビット列は、お互いに何の規則性もないビット列にエンコードされるではないか。何と言うことだ。

しかも、そのビット列の構造たるや、極めて汚らしく、綺麗なコードで逆アセンブラを書くことが出来ない。そもそも、コードがなかなか書けない。

筆者はここ何年も、規格の文面の解釈に力を入れてきた。その間に書いたコードといえば、言語の文法を説明するための数行のコードぐらいなもので、なにか本格的な動くコードは、しばらく書いていなかった。これは極めてまずいことである。筆者の役割には、C++の教育も入っているはずであるのだが、肝心の教育者が、まともなコードを書けないのでは問題だ。コードを書かないCSの教授は間違っているとBjarne Stroustrupは言った。筆者もその考えには同意しながらも、規格ばかりにかまけていて、動くコードを書かずにいた。

ただ、8086の逆アセンブラを実装するのは、動くコードを書くいい機会であるように思う。

それにしても興味深いのは、七誌氏だ。彼はOSやコンパイラーに興味があり、教育のためのこのような環境を用意するだけのちからがありながら、バイナリエディターとはなんであるかとか、エンディアンとはなんであるかと言った、基礎的な知識の教育を行うのにも躊躇しない。基礎的な知識を教えるのに躊躇している筆者と比べて、なんと意欲的なことか。

そういえば、この勉強会には、女も来ていたという点でも、興味深かった。一体、プログラマーの不自然な男女比は、どうして生じるのであろうか。肉体的な違いのためであろうか。社会的な要因のためであろうか。筆者がこの話題を持ちかけると、相手は男女とも、社会的な要因であろうと断言する。果たしてそうであろうか。

例えば、生物の科学者には女が多いと聞く。生物と言っても広いが、中には研究のほとんどが、プログラミングであるという生物学者もいる。いまや、あらゆる分野で、プログラミングは必要である。何故、不自然な男女比が存在するのであろうか。

この勉強会には、ちょまど氏が来ていた。筆者は、てっきり氏はネカマであろうと勝手な推測をしていたが、実は女であったため、驚きのあまり、第一声が極めて失礼な物言いになってしまった。聞けば、SEをしているという。その仕事は・・・いや、何も言うまい。いまさら始まった話ではないのだ。

さて、二日間かけて、8086の複雑怪奇なMOV命令のバイナリを、ある程度理解した筆者は、さっそく逆アセンブラを書き始めたいのだが、あいにくと、2014-05-pre-Rapperswil mailingが出ている。明日からは、また論文読解とレビューの忙しい日々が待っている。

池袋バイナリ勉強会には、ちょくちょく顔を出そうと思う。

そういえば、この勉強会で、C++を深く学ぶ道を進もうか、統計解析の道に進もうかと迷っている学生に出会った。筆者は統計解析の事情はよくわからないのだが、統計解析でC++を使うことはあまり一般的ではないようなので、おそらくC++が使われにくい事情があるのであろう。そもそも、規模があまりにも大きいので、単一のプログラムをカリカリに最適化して数倍の性能を出すよりも、何百台、何千台もの大規模な分散型の実行環境で力任せにぶん回すほうが効率的な分野ではないのかとも思う。筆者は、所謂フルスタック(笑)は幻想であり、そろそろ、なにか一つのものに注力したほうがいいであろうと言っておいた。それがC++であれ、統計解析であれ。

ドワンゴ広告

この記事はドワンゴの勤務外に書かれた。

この前に書いた、ドワンゴはデータマイニングエンジニアの中途採用募集をしていないというのは誤りで、実は積極的に募集しているし、採用情報にも常に記載があるそうだ。

【ドワンゴ】データマイニングエンジニア/リーダー・メンバー(正社員) | 株式会社ドワンゴ

ドワンゴはその他の分野でも本物のエンジニアを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

久しぶりにアマゾンのお気に入りリストで贈られてきたもの

久しぶりに、アマゾンのほしい物リスト経由で、筆者のもとに物が送られてきた。

今回送られてきたのは、 コーディングを支える技術 ~成り立ちから学ぶプログラミング作法 (WEB+DB PRESS plus)だ。これは、多数の言語を比較しつつ、プログラミングで使われている様々な概念を学ぶことができる本だ。

この本は、直接プログラミングを学ぶ本ではないが、プログラミングの全体像の把握に役立つだろう。

筆者にこの本をほしい物リストに追加した理由は、本の虫: プログラミングを学ぶ方法がわからないを書いた後で、人からこの本を勧められたからだ。

しかし、前回の記事の問題は、もっと根が深いと思う。変数とか関数とかループとか再帰などの、プログラミングの概念の理解ではない。コンピューターやOSの基礎的な使い方から教えて欲しいという、よくわからない話なのだ。筆者は、そこで苦労した覚えはないので、いったい何故そこを教えてもらいたいのか分からない。

ただし、コンピューターの歴史を学びたければ、うってつけの本がある。 ソフトウェアの20世紀―ヒトとコンピュータの対話の歴史だ。残念ながら、今は絶版になっているようであるが、とてもいい本だ。

さて、ふと気がつくと、本以外にも商品があるようだ。なんと、 SANWA SUPPLY TK-UCAP20 USBコネクタキャップが入っていた。

これは、USB端子に差し込むことで、ほこりの害を防ぐというプラスチック製のキャップだ。あいにくと、筆者は今、これを必要とはしていないが、ありがたく受け取っておくとしよう。贈られた以上、なにか使い道を考えなければならないが、しかしこれは、どうにも、使い道が思い浮かばない。過去に様々な理解に苦しむものが贈られてきたが、それぞれ、何かしら面白い文章をひねり出すことはできた。しかし、USBコネクタキャップという商品に対しては、面白い文章をひねり出しようがない。

筆者と妖怪ハウスは、まだまだおもしろい贈り物を募集している。贈り物は、何かしらの方法で、ブログのネタにする。