2010-11-10

耳嚢

しばらく宇治拾遺物語集を書見せるに、右書を読み終わるによって、今は、耳嚢をぞ読みける。書見なる言葉は、いつごろより使われるやうになつたものか知らず。林太郎君の笑うところの言葉なり。

耳嚢は、当時の世上の話を集めたるものにして、およそ二百年前の文なり。根岸鎮衛(1737-1815)奉行が書きたり。

ともかく、耳嚢の文章は、非常に簡単で読みやすい。私が持っているのは、岩波文庫の第二版なので、当時の校訂者である柳田國男の言葉が、巻頭に載せてある。そのなかで、「わずかに125年しかたっていないのに、もうそのままでは読めない」などと書いてある。根岸の死んだ年は、ちょうど今から225年前にあたる。とすれば、柳田國男と現在とは、100年の隔たりがある。ところで、柳田國男の文章も、現代では、もうそのままでは読めない文章である。

柳田國男は、当時(225年前)は、談話と文章の距離が、今(125年前)よりよっぽど近かったのではないかと書いている。もちろん、耳嚢の文章は、口語とは異なるが、それでも、今(125年前)の語尾だけ見た目だけの言文一致よりは、よほど優れていたのではないかと書いている。興味深いことだ。

2010-11-08

体温が上がると体がかゆくなる

私は物心ついたころから、体温が上がると体がかゆくなるという症状に悩まされている。どのような状況で起こるかというと、強力な冷房のきいた場所から暑い場所に移動したとき、熱い食べ物を食べたとき、風呂に入ったとき、急激な運動、などである。思うに、体温の急な上昇が問題ではないかと思う。

ところが、どうも今年の冬は、さらにひどくなっている。最近、寒くなったので、当然厚着をして出かけているのだが、10分ほど普通に歩いただけで、全身かゆくてたまらなくなる。かといって、外套を着ないわけにも行かない。普通に歩くだけでも体温は上がるのは当然なのだが、昔はここまでひどくはなかった。

かゆみは10分ほどもすれば収まるため、それほど日常生活に支障はないものの、今年は格別に頻度が高い。どうしたことだろう。一度医者にでも相談するべきなのだろうか。

2010-11-07

OldNewThing:時刻合わせの際、日付が違っていると失敗する理由

Why does the Win32 Time service require the date to be correct before it will set the time? - The Old New Thing - Site Home - MSDN Blogs

時刻同期の際に、日付が違っていると、処理は失敗し、次のようなエラーメッセージが返ってくる。「Windowsは時刻をtime.windows.comと同期させる際に、エラーが発生しました。セキュリティ上の理由により、Windowsは時刻を同期できません。理由は、日付が違っているためです。日付を修正して再試行してください」。セキュリティ上のリスクとは何だ?

まず、問題を解決したい人は、エラーメッセージに従うことだ。日付を正しく設定して、再試行すべきである。もし、それでも失敗する場合、時間をある程度近い値に設定すべきである。時刻がある程度近くなれば、timeサーバーと正常にやり取りできる。

閑話休題(それはさておき)、ここでいう、セキュリティ上のリスクとは何か。

一見すると、サーバー側が、時刻があまりにも間違って設定されているクライアントを弾いているように見える。しかし、事実は逆である。クライアントが、悪意のあるtimeサーバーの攻撃を防いでいるのである。

ケルベロス認証プロトコルは、お互いが同じ時刻を使っていることを前提としている。(多少の誤差は許容範囲だが)。もし、攻撃者が、例えばDNS poisoningなどで、クライアントの時刻を、悪意あるサーバーと同期させた場合、攻撃者は不正な時刻(大抵は過去の時刻)を用いて、次の攻撃の足がかりにすることができる。

Windows Timeサービスのデフォルトの設定では、15時間以上も違っている日付を拒否するようになっている。このKB記事に従えば、設定を変更することもできる。なお、このKB記事が、本文執筆の主要なソースとなっている。

2010-10-30

cookieの歴史と欠点

lcamtuf's blog: HTTP cookies, or how not to design protocols

これは面白い。

AdobeとMcAfeeはクソだ

今日、突然、画面上に不思議なウインドウがでた。何事かと思ってよく見ると、何とMcAfeeであった。おかしい。私はMcAfeeをインストールした覚えなどない。それに、このウインドウは、ブラウザのポップアップでもない。明らかに独自のウインドウである。南無三、やられたか。これはMcAfeeのフリをしたmalwareに違いない。しかし何故だ。そもそも最近は、ネット上から実行ファイルをダウンロードして実行ということすらしていないはずだ。

ともかく、どのようなプロセスなのか調べることにした。すると、なぜかファイルパスがProgram Files下にある。よく作ったものだ。まるで本物のMcAfeeのようだ。いや、まてよ、Program Files下だと? Program Files下に書き込むためには、Administrator権限が必要である。どうやってUACを突破したのだ。いや、仮にUACを突破したとしても、わざわざProgram Files下に書き込む必要はあるのか。malwareならば、もっと便利な場所がいくらでもあるだろうに。

不思議に思って調べると、スタートメニューにも、McAfeeの項目が付け加えられており、コントロールパネルの「プログラムと機能」にも、McAfeeのアンインストール項目が表示されている。どうもおかしい。偽物にしてはできすぎている。その表示を信じるならば、インストールした日は、2日前である。

2日前といえば、確かFlash Playerのアップデートをしたような気がする。まさか・・・そのまさかだった。クソAdobeは、デフォルトでクソMcAfeeをバンドルしているのだ。しかし、そんなオプション、全く気がつかなかったぞ。クソにも程がある。

つまり、このMcAfeeは本物らしい。Flash Playerのアンインストールを本気で考えてしまった。いずれにせよ、もう数年で、Flash Playerはいらなくなるだろう。

アンインストール後、念のためにMark Russinovichのautorunsを使って調べたが、見慣れない自動実行やサービス、ドライバーの類は見つからなかった。しかしまぁ、なんだかなぁ。

2010-10-29

ニコニコ動画のアカウントを消した

ニコニコ動画を見なくなって久しい。ところが、今日になって、ニコニコ動画からのSPAMメール(連中に言わせると、通知メール)が届き始めた。どうやら、誰かが自分のリストを購読するたびに、SPAMが送られてくるらしい。通知メールを送らない設定にもできるようだが、通知メールの種類があまりにも多く、一つ一つ手動で選択しなければならないという、クソふざけたUIとなっている。しかも、ひとつ設定するごとに、無効にしているメール一覧のページにとばされるので、そのままもう一つ無効にしようとしても、実は有効にしているだけだという始末。

バカにしているにも程がある。即座にアカウントを消した。

思えば、ニコニコ動画は、インターネット史に残るサービスではあったと思う。最初の一年ぐらいは面白かったが、ここ数年は、まともにみなくなっていた。遅い。埋め込み動画はChromeで見れず、一度埋め込み動画を再生しようとしてしまうと、公式サイトに飛んでも、その動画が読み込めなくなってしまう。そもそも、コメントが面白かったのは初期だけで、すぐに、常にコメントを無効にしていたのだ。

結局、ひとつの時代が終わったということか。

C++0xのUnion

C++0xでは、unionの制限がかなり取り払われたので、こんなことができる。

union U
{
    std::string str ;
    std::vector<int> vec ;

    // コンストラクターとデストラクターは、暗黙的にdeleteされているので、
    // ユーザー定義が必要。
    U() { }
    ~U() { }
} ;

int main()
{
    U u ;

    new ( &u.str ) std::string( "hello" ) ;
    std::cout << u.str << std::endl ;
    u.str.~basic_string() ;

    new ( &u.vec ) std::vector<int> { 1, 2, 3 } ;
    for ( auto i : u.vec )
    { std::cout << i << std::endl ; }
    u.vec.~vector() ;

}

まあ、なんのことはない。Uのオブジェクトは、std::stringとstd::vector<int>のどちらかを格納できるだけのサイズを持っているし、またアライメント要求なども適切に行われるので、placement newができるという話だ。

最初、~basic_stringと書くべきところを、~stringと書いてしまい、エラーになった。typedef名の弊害と言える。もちろん、テンプレート実引数は省略できる。なぜならば、オブジェクトの型は、コンパイル時に分かっているからだ。

この手のことは、別に新しいテクニックというわけでもないが、自前でストレージのサイズやアライメントを設定せずにすむので、よりポータブルに書ける。

2010-10-28

ドイツ軍の戦車の生産台数を割り出せ!

German tank problem - Wikipedia, the free encyclopedia

第二次世界大戦当時、連合国は、ドイツの戦車の生産台数を知りたかったが、その方法がなかった。

ドイツの戦車には、シリアルナンバーが付与されていた。捕獲した何台かの戦車から、そのシリアルナンバーを知ることができた。さて、このシリアルナンバーは、明らかに、インクリメントされている。すでに知っているいくつかのシリアルナンバーから、ドイツの戦車の生産台数を割り出すことはできぬものか。

そして、実際に、ほとんど同じ数字を割り出したらしい。なかなか興味深い。

今の世の中では、戦車の保有台数を隠すことに、あまり意味はないかもしれないが、極力敵国に情報を渡さないということを考えると、シリアルナンバーはUUIDなどにしておいたほうが無難なのかもしれない。

連合国はどうやってドイツの戦車生産数を割り出したのか - スラッシュドット・ジャパン

ちなみに、こんな話も。当時の日本人とアメリカ人の食事の違いで、大便の量が異なっていたため、誤った推定をしてしまったというお話。

連載 健康談義 第3回目「健康に生きる」

2010-10-26

これが実現したらいいのに

三単現の“s”20年めどに廃止 米・教育局

ただしソースは虚構新聞。ああ、ソースが虚構新聞でなければいいのに。

ほかにも、articleとpluralを廃止して欲しい。

他の言語版:男性複数与格を2018年めどに廃止─ロシアでも言語ゆとり政策 : bogusnews

2010-10-25

ややこしいnoexcept

MLに面白い話題が上がっていたので紹介する。

noexceptには、二つの意味がある。

1. 例外指定としてのnoexcept

void f() noexcept ; // noexcept(true)と同じ
void g() noexcept(true) ; // 例外を投げない
void h() noexcept(false) ; // 例外を投げる

この場合、文法は、noexcept( 定数式 )という文法になる。定数式がtrueと評価されれば、無例外といういみである。

2. noexcept演算子

void f() ;
void g() noexcept ;

int main()
{
    noexcept( f() ) ; // false
    noexcept( g() ) ; // true
}

この場合、文法は、noexcept( 未評価式 )となる。未評価式が例外を投げる可能性があれば、falseを返す。例外を投げないと保証できる場合は、trueを返す。例外を投げる可能性というのは、throw式が含まれているかや、noexcept(true)と指定されていない関数を呼び出すかどうかで判断される。たとえ、実際にはthrow式が含まれていなくても、無例外指定がされていない関数の呼び出しは、falseと評価される。noexcept演算子は、定数式である。

さて、以下の例を考えてみよう。

void f() noexcept( noexcept( g() ) ) ;

これはどういう意味かというと、g()という未評価式が、例外を投げる可能性がなければ、関数fは無例外指定されるという意味である。一方、

void f() noexcept( g() ) ;

これは、g()という定数式が、trueと評価された場合に、関数fは無例外指定になるという意味である。もちろん、g()という式が定数式でなければ、エラーとなる。

この文法はどう考えてもややこしくないか。

実は、以下のような文法も考慮されていたらしい。

void f() noexcept if true ;

ここでは、ifというキーワードを使うことによって、次に定数式を指定している。しかし、noexcept(true)の方が分かりやすいという意見の方が多かったため、こうなった。また、別の拡張で、似たような文法を使いたい時に困るという意見もあった。別の拡張というのは、ほかでもない、明示的なSFINAEである。

2010-10-24

親知らず三週間目

一週間前、つまり親知らずを抜いてから二週間目では、傷はふさがったものの、親知らずを抜いた影響で、親知らずの近くの歯が、何も悪くないのに痛んでいた。抜歯後、三週間もたった今では、痛みはない。しかし、親知らずを抜いた後が穴になっていて、モノを食べると詰まる。結果として、歯磨に苦労する。

盗難バイクを受け取った少年、一切の電子機器の使用を禁止される

Court Rejects Probation Rules On Teen That Ban Him From Using Social Networks Or Instant Messaging Programs | Techdirt

shall not use a computer that contains any encryption, hacking, cracking, scanning, keystroke monitoring, security testing, steganography, Trojan or virus software.

is not to use a computer for any purpose other than school related assignments.

暗号の利用禁止ということであれば、SSLを利用したWebサイトは使用できなくなる。それどころではない。Webブラウザーやメールソフト自体が使用禁止だ。そもそも、WindowsやMacOSやLinuxといったモダンなOSは、暗号技術がふんだんに使われているので、使用禁止である。コモドールでも使うのだろうか。いやしかし、コモドールは暗号フリーだろうか。

それどころではない。テレビやゲーム、DVDなども使用禁止である。大昔の真空管テレビででもない限り、これらの機械には、暗号技術がふんだんに使われている。もちろん、DRMのかかった音楽や動画、電子書籍なども利用禁止である。また、電話も使えないだろう。

電子透かしも、DRMを利用不可能にする。しかし、現在では、多くの音楽CDに、電子透かしが埋めこまれている。つまりこの少年はCDを再生することすらできまい。

キーストロークモニタリングの禁止も厄介だ。なぜならば、現代のほとんどのソフトウェアは、キー入力を監視している。もちろん、OSはまず筆頭にあがる。キーモニタリングをしていないソフトウェアというのは、OSのカーネルのごく一部でしかないだろう。しかし、それ単体では存在できない。そもそも、BIOSからして、キーモニタリングしているではないか。

クラッキングやスキャニングの定義も曖昧である。セキュリティテストには、おそらくファイヤーウォールやアンチウイルスソフトなども含まれるであろう。これらも実に効果的に、OSを使用不可能にしている。あるコンピューターにウイルスが入っていないと断言することはできない。なぜならば、工場出荷段階で、HDDやフラッシュメモリやEPROMにウイルスが混入している可能性があるからだ。

もし、この少年の住んでいる家が、物理的なカギのかわりに、電子キーを用いていた場合、この少年は一人で家に入ることすらできないであろう。

裁判所の命令を守るためには、この少年は現代技術を排斥するアーミッシュ - Wikipediaの住んでいる場所に引越して暮らすしかないであろう。しかし、アーミッシュとて、道交法をまもるためにしかたなく、馬車にライトを取り付けたりしているのだ。果たしてそのライトには、一切のコンピューターと認められる電子回路が組み込まれていないものかどうか、心配である。

このように、現代社会における暗号の禁止は、単なるパソコンの利用の禁止以上の、あらゆる電子機器の使用禁止という意味を持つ。あらゆる電子機器の使用を禁止された場合、すでにその存在に依存した社会では、暮らしていけないだろう。一体どうしたらこんな馬鹿げた命令を下せたのか、理解に苦しむ。

詳しくは元ソースを参照してもらいたいが、これには抜け穴があって、「学校の宿題のために、学校内や家庭内の監視された環境なら使用可能」という文章がある。おそらく、あらゆる電子機器の利用が、学校の宿題という名のもとに行われるのであろう。そもそも、自宅のドアを自力で開けられなければ、専属の秘書でも雇わない限り、学校に登下校できないわけだし。

そもそも、「盗難バイクを受け取った」という罪が、どうしてコンピューターの使用不可という命令になるのか分からない。現代社会は、コンピューターなしでは、到底暮らしていけないというのに。たとえば、銀行にも行けない。信号機の利用はコンピューターの利用になるだろうか。

働く人たちが答える「質問ある?」スレまとめが面白い

働く人たちが答える「質問ある?」スレまとめ - NAVER まとめ

一部、明らかに怪しいものもあるが、そこは、嘘を嘘と見抜く必要がある2ch.netならではだろう。

昔の2ch.netでは、この手のスレは、「某ですが何か?」などというスレタイだったものだが、最近は「某だけど何か質問ある?」という、普通の形に変わってしまっている。これも、2ch.netの大衆化に伴って、2ch語が廃れたためだろう。もっとも、この「某ですが何か?」というのは、あまり真面目なスレには用いられなかった記憶もあるが。たしか、「先行者ですが何か?」とか、「プログレッシブナイフですが何か?」などというスレばかりだったように記憶している。

思うに、隠語というものは、最初は小数の集団の中において使われていたのが、集団が増えるにしたがって、一般化するか、死語となってしまうかの、どちらかになるのであろう。例えば、寿司屋で食べ終えた後にもらうお茶の事を、「あがり」というが、これとて、もとは寿司屋の店員同士の符丁だったわけだ。

2010-10-23

ネズミーランドのサイン

1日でどれだけディズニーキャラにサインをもらえるか | オモコロ特集

中の人はカリグラフィーの練習までしなけりゃならないのか。

そういえば、私は日本人でも珍しい、あのネズミの住む夢の国に入国したことのない人間である。私は小中高とド田舎で暮らしていたが、学校のクラスのほぼ全員は、一度はネズミーランドに行っていた。恐ろしい集客力である。

2010-10-22

nested_exceptionの使い方

nested_exceptionは、例外をネストするための、簡単なクラスである。ユーザー定義のクラスから継承して使うことを想定されている。

struct CustomException : std::nested_exception
{ } ;

int main()
{
    try {
        try {
            try {
                throw 123 ; // 何らかのエラー
            } catch( int e )
            { // ここで、元の例外の値を保持しつつ、別の例外を一時的にthrowしたい
                std::cout << e << std::endl ;
                throw CustomException() ;
            }
        } catch( CustomException e ) 
        {
            std::cout << "CustomException" << std::endl ;
            std::rethrow_if_nested( e ) ; // 例外を処理し終わったので、元の例外をthrowする
        }
    } catch( int e )
    { // 元の例外が、さらに外側のハンドラへ届く
        std::cout << e << std::endl ;
    }
}

では、nested_exceptionの実装どうなっているのか。実は、特別なことはなにもしていない。以下のような実装になる。

namespace std {

class nested_exception
{
private :
    exception_ptr ptr ;
public:
    nested_exception() noexcept
        : ptr( current_exception() ; )
    { }

    nested_exception(const nested_exception&) noexcept = default ;
    nested_exception& operator=(const nested_exception&) noexcept = default ;
    virtual ~nested_exception() = default ;
    // access functions
    [[noreturn]] void rethrow_nested [[noreturn]] () const
    {
        if ( ptr == nullptr )
            terminate() ;
        else
             rethrow_exception( ptr ) ;
    }
    exception_ptr nested_ptr() const
    {
        return ptr ;
    }
} ;

} // namespace std

これは単に、コンストラクターでcurrent_exceptionを呼び出しているだけである。つまり、nested_exceptionを継承しなくても、自前のクラスに同じ機能を組み込むことも可能である。しかし、このコードは、誰が書いても同じようになる。わざわざ自前で書かなくてもいいように、nested_exceptionがある。

しかし、わざわざnested_exceptionを継承するのすら面倒ではないか。そう思った君は、一流のC++プログラマーの素質がある。プログラマーは、怠惰であればあるほど、優れているのだ。第一、自分でコードを書くのは、バグのもとではないか。そういうズボラな一流プログラマーのために、throw_with_nestedという関数が用意されている。これは、実引数のクラスが、nested_exceptionを継承していれば、そのままthrowし、そうでない場合は、自動的にnested_exceptionと、実引数のクラスとを継承した、何らかの型を生成してthrowするのだ。

// 俺様お手製の超スゲー例外クラス
struct My_Ultra_Super_Deluxe_Exception
{
} ;

void f()
{
    try {
        // 例外を投げるかもしれない処理
    } catch( ... )
    {
        std::throw_with_nested( My_Ultra_Super_Deluxe_Exception() ) ;
    }
}

このようにすれば、例えば、以下のように書けるわけだ。

void g()
{
    try {
        f() ;
    } catch( My_Ultra_Super_Deluxe_Exception & e )
    {
        // My_Ultra_Super_Deluxe_Exceptionに対する例外処理
        // ネストしている場合、元の例外を再throwする
        std::rethrow_if_nested( e ) ;
    }
}

このようにすれば、元の例外を保持しつつ、別の例外を投げることができる。ハンドラ側では、ある例外に対する処理を行い、もしネストされていれば、再び例外をthrowすることができる。

throw_with_nestedの実装例は、本の虫: pre-Batavia mailingの簡易レビューを参照。throw_if_nestedも、ほぼ似たようなメタプログラムで実現できる。

もちろん、これらの関数は、すべて自前で実装可能である。ただし、一流のメタプログラマーではない限り、このようなメタプログラミングをするのは難しいので、標準ライブラリが用意されているのだ。

2010-10-20

pre-Batavia mailingの簡易レビュー

ISO/IEC JTC1/SC22/WG21 - The C++ Standards Committee

N3139: An Incomplete Language Feature

関数の実引数に、空の初期化リストを渡せない問題の修正。以下のようなコードがwell-formedになる。

struct S
{
    S( std::initializer_list<int> ) ;
} ;

// デフォルト引数に空の初期化リスト
void f( S s = { } ) ;

int main()
{
    // 関数の実引数に空の初期化リスト
    f( { } ) ;
}

N3140: Cleanup of Pair and tuple

C++0xの新機能に対応させようとしたら、std::pairとstd::tupleの文面がだいぶおかしくなってしまったので、これを統一して修正。

N3142: Adjustments to constructor and assignment traits

has_*_constructorとhas_*_assignというtraitsは、あたかもコア言語的な響きがする。しかし、ライブラリ作者としては、ある型Tがコンストラクターを持っているかどうかは、別にどうでもよい。ライブラリ作者が知りたいこととは、ある型Tに対して、T()とか、T(U)などと書いてよいかどうかである。したがって、hasという名前は相応しくない。

すべてのhas_*_constructorとhas_*_assignという名前のtraitsを、is_*_constructibleと、is_*_assignableという名前に変える提案。

N3143: Proposed wording for US 90

現行のstd::forwardの定義では、以下のコードがコンパイルできない。

#include <utility>

struct Base { Base(Base&&); };

struct Derived
: private Base
{
    Derived(Derived&& d)
        : Base(std::forward<Base>(d)) { }
};

// error: forward can not access Derived's private Base

なぜならば、DerivedからBaseへのキャストは、Derivedクラスの外からは、アクセス指定の制限のため、行えない。すなわち、std::forwardの中では、行えない。この問題は、std::forwardを、lvalue referenceとrvalue referenceでオーバーロードすることによって解決する。また、std::moveのreutrnに、static_castが抜けているので、あわせて修正。

やはりstd::moveのreturnにstatic_castが抜けているのは規格の間違いだったのか。だいぶ前にstd::moveを自分で実装して、おかしいと思ったのだ。

N3144: Wording for US 84

throw_with_nestedの文面の修正。Tがnested_exceptionを継承していない場合、Tとnested_exceptionを継承したクラスが、forwardによって構築されて投げられるらしい。実装例はこんな感じだろうか。attributeを消し、using宣言をtypedefに置き換えれば、gccで動くことを確認。最近書くコードは、こんなのばかりだ。まったくもって実務的ではない。

namespace std {

namespace detail {
template < typename T >
struct unspecified_exception
    : public std::remove_cv< typename std::remove_reference<T>::type >::type,
      public std::nested_exception
{
    template < typename U >
    unspecified_exception( U && u )
        : T( std::forward<U>(u) )
    { }
} ;

template < bool b >
struct throw_with_nested_impl
{
    template < typename T >
    [[noreturn]] static void invoke( T && t )
    {
        throw std::forward<T>(t) ;
    }
} ;

template<>
struct throw_with_nested_impl<false>
{
    template < typename T >
    [[noreturn]] static void invoke( T && t )
    {
        using type = typename std::remove_cv< typename std::remove_reference<T>::type >::type ;
        static_assert( std::is_class<type>::value, "throw_with_nested:T must be a non-union class type.") ;
        throw unspecified_exception<type>( std::forward<T>(t) ) ;
    }
} ;

} // namespace detail

template < typename T >
[[noreturn]] void throw_with_nested( T&& t )
{


    using plain_T = typename std::remove_reference<T>::type ;
    constexpr bool b = std::is_base_of<
        std::nested_exception,
        plain_T >::value ;
    detail::throw_with_nested_impl<b>::invoke( std::forward<T>(t) ) ;
}

} // namespace std

N3145:Deprecating unary/binary_function

名前通り。

N3146:Recommendations for extended identifier characters for C and C++

C++0xでは、Basic source character set外の文字を、識別子として使うことを許可した。具体的にどのような文字が許可されるのかは、実装に依存するが、規格での推奨事項(空白文字は好ましくないなど)を付け加える提案。

N3148 - throw() becomes noexcept (Version 2)
N3149 - From Throws Nothing to noexcept
N3150 - Removing non-empty dynamic exception specifications from the library

名前通り。throw()をnoexceptで置き換えと、Throws: Nothingをnoexceptに変更することと、空ではない動的例外指定を削除。

N3151: Keywords for override control
N3163: Override Control Using Contextual Keywords

Rapperswill会議において、attributeのbase_check、override、hiding、finalは、キーワードで置き換えることが、投票により決定した。問題は、キーワードをどうするかということだ。もちろん、キーワードは、既存のコードの互換性を確保するため、絶対に使われていないような名前でなければならない。そのため、ML上ではbikeshedding(どのように自転車小屋を建てるべきかという、正直どうでもいい議論)が盛んであった。

キーワード案が採用されるならば、とてつもなくuglyなキーワードが採用されることは確実である。ここで、Contextual Keyword(文脈依存キーワード)という案がある。これは、ある名前を、ある特定の場所でのみ、キーワードとして扱うというハックである。JavaやC#が、すでにこれをやっている。このようなハックは、コンパイラーや文法ハイライトの実装を難しくする。ただし、C++はすでに、他の言語とは比べものにならないぐらい実装が難しい言語である。この程度の実装は、他のもっと難しい昨日の実装に比べれば、屁みたいなものである。それに、このような実装をすれば、ユーザー側の負担は全くない。既存のコードを再コンパイルするコストは計り知れないのである。

N3152: Progress guarantees for C++0x

C++0xは、マルチスレッドとデータ競合に関して、Progress guaranteesというものを、全く定義していない。これでは、プログラマがまともにコードを書くことなど不可能ではないか。というNBコメントに対して、progress guaranteesというものを厳格に定義することは、非常に難しいということを説明したペーパー。

N3154: US 19: Ambiguous use of "use"

規格の文面では、useという言葉が使われている。ところで、3.2では、useという言葉を、特別な意味を表す用語として定義している。しかし、文面では、useを一般の英単語としても使っており、区別がつかない。そのため、3.2のuseを、odr-useという特別な用語に置き換えることにする。3.2の意味でuseという単語を使っている文面も、odr-useに置き換える。

N3155 - More on noexcept for the language support library
N3156 - More on noexcept for the diagnostics library
N3157 - More on noexcept for the General Utilities Library

既存の標準ライブラリの中で、noexcept指定できる関数を模索。

N3158: Missing preconditions for default-constructed match_result objects

名前通り。

N3164: Adjusting C++ Atomics for C Compatibility

C1XとC++0xのatomicの互換性の向上

N3165: Allocator Requirements: Alternatives to US88

allocator_traitsの導入によって、allocatorのrequirementsが大幅に減った。では、実際に規格上のrequirementsも弱めるべきか。C++03との互換性はどうするのか。といったことを論じている。このペーパーにおける提案は、LegacyAllocator Requirementsを付け加えるというものである。ちなみに、legacy_allocator_adaptorというwrapper classを追加しようというアイディアは、却下された。

N3166=10-0156 - Destructors default to noexcept

例外指定のないデストラクターは、デフォルトでnoexcept(true)にしようという提案。一般に、デストラクターから例外を投げるべきではない。すでにC++98の段階で、、STLの全クラスは、デストラクターからの例外のthrowを禁止されている。また、STLに渡すテンプレート実引数の型も、デストラクターから例外をthrowしてはならないと定められている。C++0xでは、デストラクターは明示的にnoexcept(false)などを指定した場合のみ、例外を外に投げられるようになる。

N3167=10-0157 - Delete operators default to noexcept

delete演算子を、デフォルトでnoexceptにする提案。当然、deallocation functionも、この影響を受けて、デフォルトでnoexceptになる。

N3168: Problems with Iostreams Member Functions (Amended from US 137)

また誰にも使われないiostreamの修正か!

N3169: A Few Small Library Issues

これも名前通り。

N3170: Clarifying C++ Futures

futureをどのような目的で使うかということに関して、委員の間でも、意見の不一致がみられた。そこで、futureをどのような場合に使うかという例を示す。また、小さな文面の修正も含んでいる。

N3171: Proposed resolution for US104: Allocator-aware regular expressions

regexがbasic_stringに指定するアロケーターに関して、意味を明確化。

N3172: Allocators for stringstream (US140)

stringstreamがbasic_stringに指定するアロケーターに関して、意味を明確化。

N3173: Terminology for constructing container elements (US115)

コンテナーの文面で、要素の構築に関して、CopyConstructibleとMoveConstructible、引数による構築を、事実上、再定義してしまっている。これを、あらかじめ定義された用語を使うように修正。

N3153: Implicit Move Must Go

暗黙的なムーブコンストラクターとムーブ代入演算子の生成は、C++03のコードとの互換性の問題を引き起こす。ゆえに、規格から消すべきである。題して、「暗黙のムーブは死ぬべき」

N3174: To move or not to move

ムブるべきか、ムブらざるべきか、それが問題だ。ここでは、暗黙に生成されるコピーとムーブによる問題点を列挙している。筆者は、たとえ暗黙のムーブがなかったとしても、暗黙のコピーにより、問題は残ることを論じた上で、現状のFCDの文面を保持するべきだと結論している。また、暗黙のコピーは、ユーザー定義のコピー、ムーブ、デストラクターがある場合、生成をdeprecatedにするべきだと提案している。

つまり、この問題は暗黙のムーブだけではなく、暗黙のコピーにも起こりえるのだ。暗黙のムーブが生成されない状況では、暗黙のコピーも、本来、生成されるべきではない。いまからコピーに対してそのような変更を行うのは無理なので、せめてdeprecatedにするべきだと提案している。

N3178: emplace Broken for Associative Containers

現在のemplaceの定義では、連想コンテナには適用できない。この修正は、現時点では、容易ではない。さてどうするかという短いペーパー。そもそも、STLのコンテナーは、現代からみれば、設計が悪いのだ。だからemplaceなんてものが必要になる。やれやれ。互換性ハ神聖ニシテ侵スヘカラス。

N3179: Move and swap for I/O streams (US138)

basic_istream, basic_ostream, basic_iostreamにおいては、ムーブコンストラクターは、実はムーブしない。ムーブ代入演算子も、実はムーブしない。swapも、実はswapしない。しかも、これらの関数はprotectedであり、ユーザーコードからは使用できない。

しかし、これらのクラスはabstract classではないし、ユーザーコードから使用すべき妥当な理由もある。まあ、これもiostreamだ。したがって誰にも省みられることのない修正と言える。

2010-10-18

ロボットダンスもここまできたか

片足で立っている瞬間もある。すごい。

2010-10-17

残すほど価値のあるものはない

マスコミやGIGAZINEが伝えないマジコン規制の本当の恐ろしさ - P2Pとかその辺のお話@はてな

現在、私の知る限り、DRMが掛かっている書籍、ゲーム、音楽、映画などは、残すに価するほどのものはない。だから、残すという話は、私にとってはどうでもいい。DRMをかけたことによって、将来的に困るのは、コンテンツホルダー側である。彼らの作品は残らないのだから、どんなに作品が人気であったとしても、将来、それによって得られたはずの利益が得られなくなるはずだ。

ただし、一体マジコンのごときものを法律で禁止するのは、危険である。所有しているコンピューターを、どのように使おうが、所有者の自由であるはずだ。マジコンが禁止されるということは、その自由を奪うということである。

もっともDSは、自由にプログラミングできないようなコンピューターである。そんなコンピューターは、始めから所有する価値がない。そして、DSというハードも、将来残らないだろう。

IBM PC/AT互換機は、いまだに残っている。これは、彼らが独占的な権利を主張しなかったからである。もし当時のIBMが排他的な考え方をしていたならば、今のIBMのPC市場で地位はなかっただろう。

デスクリムゾンがWindowsに移植されるらしい

伝説のクソゲー『デスクリムゾン』がWindowsに移植&フリー公開決定、「あの仕様」も完全再現 : はちま起稿

あの伝説のクソゲが移植されるのか。

2010-10-16

親知らず二週間目

親知らずを抜いてから二週間。傷はふさがったが、親知らずがあった場所の隣の歯が痛む。つまりは、一番奥の歯ということだ。特に今朝は酷い。

これはどうすべきなのかよく分からない。表面上、虫歯はないようだ。しばらく痛みが続くようならば、もう一度歯医者に良く必要があるのだろうか。

2010-10-15

wired.comによるBjarne Stroustrupへのインタビュー

Oct. 14, 1985: C++ Adds to Programming | This Day In Tech | Wired.com

なかなか面白かった。

Michael J. Fox、Back To The Futureの予告編をリメイクすること

当時の予告編

リメイク

だいぶ頑張ったようだ。それでもやはり、体の震えを完全に止めることはできないらしい。

2010-10-14

VC10は新しいVC6

Visual C++ 10: 10 is the new 6 | VisualStudio | Channel 9

まあ、確かにVC6と同じくらいクソだということは確かだ。一行に数十文字ぐらい書いただけでクソ遅くなるIDE付きなのだから。C++の規格準拠度も、あきれ返るぐらい悪い。実に悪い。

MSVCのランタイムとスレッドとリソースリークの関係

本の虫: いまだに変な宗教が流行っているを書いたところ、どうもこのへんの情報は、あまり知られていないようであるので、できるだけ分かりやすく解説することにした。

Cの標準ライブラリは、恐ろしく古いライブラリである。その設計は、マルチプロセッサ(コア)上で動作するマルチスレッドが当然の現代では、あまりよろしくない。

たとえば、strtokという関数がある。この関数は、引数として渡された文字列を、内部のバッファにコピーする。次のstrtokの引数には、NULLを渡すことで、そのコピーされたバッファから、次のトークンの場所へのポインターを返すのである。

void f( char const * ptr )
{
    char const * p1 = strtok( ptr, " " ) ;
    char const * p2 = strtok( NULL, " " ) ;
}

しかしもし、strtokが複数のスレッドから呼ばれた場合、どうなるのだろうか。引数にNULLを渡して、先程の文字列のコピーから、次のトークンの場所を返してくれることを期待しているのに、別のスレッドによって、勝手に内部の文字列が書き換わってしまっては困る。

この、複数のスレッドから利用しても大丈夫かどうか、ということは、非常に重要である。これをスレッドセーフと呼んでいる。

したがって、あるスレッドがstrtokを呼んでも、別のスレッドの内部バッファまで変更しないように実装しなければならない。これには、スレッドごとに、メモリーを確保する必要がある。

Cの標準ライブラリには、このようなスレッドアンセーフな設計のライブラリが山ほどある。Cの標準ライブラリは、まともなC++プログラマーならば、まず使おうとは思わないだろう。

言うまでもなく、このような設計は、現代ではクソである。当時のプログラマーを問い詰めたいところなのだが、まあ、すでになされたものは仕方がない。今さら互換性を失うわけにもいかないのだ。クソなことにはかわりはないが。

さて、このような、スレッドごとの動的に確保されるメモリーのアドレスを保持しておくための変数が必要になる。Windowsでは、TLS(Thread Local Storage)という仕組みが、OSによって用意されている。これにアドレスを格納しておけばいいのだ。

Windowsには、CreateThreadという、スレッド作成用のAPIが存在する。しかし、MSVCでは、独自のスレッド作成用の関数、__beginthreadexを使用することが推奨されている。これはなぜかというと、標準ライブラリに必要な、スレッドごとのメモリを確保、解放するためである。

では、もしMSVC上で、CreateThreadを用いてスレッドを作成したら、どうなるのか。スレッドごとの動的に確保されたメモリーを必要とする、一部の標準ライブラリは、動かなくなるのだろうか。幸い、その心配はない。MSVCの標準ライブラリの実装は、スレッドごとの動的なメモリーを必要とする関数が呼ばれたときに、TLSを確認し、もし、メモリーが確保されていなければ、その場で確保して、何事もなかったかのように処理を続ける。これによって、「動かない」という最悪の自体を回避できる。

しかし、ここでひとつ、問題がある。その確保したメモリーは、いつ解放すればいいのだろうか。もちろん、スレッドが終了するとき、すなわち、スレッドというリソースが解放される時である。しかし、スレッドの終了をどうやって補足すればいいのか。スレッドの終了を補足する方法は、なかなかにややこしい。

スレッドが、プロセスの終了まで、ずっと生存しているのならば、問題はない。Windowsにおいては、プロセスの所有するリソースは、プロセスというリソースの解放に伴い、自動的に解放されるからだ。プロセスが解放されたとき、後には何も残さない。もちろん、他のプロセスがプロセスハンドルを掴んでいる場合は、プロセスハンドルを維持するためのリソースは生き残っているが、それはまた別の話である。プロセスのスレッドはすべて開放されているが、まだプロセスが開放されていない状態である。

問題は、CreateThreadによるスレッドの生成、一部の標準ライブラリの仕様、スレッドの破棄を繰り返すプログラムである。そのようなプログラムでは、スレッドを生成、破棄するたびに、解放できないメモリーが取り残される。すなわち、リソースリークである。

実は、DLLを使えば、このスレッドの終了を補足するのは、非常に簡単である。なぜならば、プロセスに読み込まれている、すべてのDLLのDllMain関数は、プロセスのあらゆるスレッドの終了時に、DLL_THREAD_DETACH通知を受ける。この通知を使えば、TLSに保存されているアドレスのメモリーを解放できるのだ。

つまり、DLL版のランタイムライブラリを使えば、CreateThreadやThread Poolによって生成されたスレッドから、一部の標準ライブラリを使っても、リソースはリークしない。スレッド終了時に、必ず解放される。しかし、スタティックリンク版は、この方法が使えない。そして、MSVCの実装も、何とかするようには出来ていない。結果、リソースリークする。

そもそも、他ならぬマイクロソフト自身が、スタティックリンク版を使うなと明言したのが、確かVS2005の頃だった。スタティックリンク版のCRT、ANSI版のAPI、Unicode以外の文字コード、Windows XP、x86の32bitコード、IBM PCのBIOS、これらは皆、速やかに滅ぶべきものどもである。いやしくもプログラマーたるものは、実装の美しさを尊ばねばならぬ。特に、64bitコードの関数の呼び出し規約の統一は、涙が出るほどありがたいはずだ。それにも関わらず、旧態依然の古めかしい知識と技術に固執する。愚かなること、これに過ぎたるはなし。

追記:はてなブックマークのコメントより、

前半は良いのだが、後半のCreateThread()でのメモリリークについては、ちょっと最新の仕様とあってない気がする。Windowsは途中からスレッドハンドルをクローズしなくてはならない仕様になった

これはCRTとは何の関係もない話である。これはWin32 APIの仕様だ。この記事は、Windows、MSVC環境下における、スレッドとCRTのリソースリークについて書いているので、Win 32 APIの仕様には特に触れなかった。

ただし、これもスレッドとリークに関連はある。もちろん、CreateThreadで得たスレッドハンドルは、CloseHandleによって解放しなければならない。なぜならば、CloseHandleを呼び出さなければ、まだスレッドハンドルを、そのプロセスで使っているということだからだ。もちろんこれは、CreateProcessにおけるプロセスハンドルにも言えることだ。してみれば、Win32 API全般に関する注意点であって、特にスレッドに限定される話ではない。

写真を取らなくてもよい七つのもの

7 things you really don't need to take a photo of - The Oatmeal

1. 酒場

「このマンゴーティーニ頼んだの、だあれ?」
「あたしに決まってんだろボケ。いまからさ、写真とって世界中に見せびらかそうよ。あたしらがこんなにもバカやってるところをさ。マジでオランウータンみてーじゃん、あたしら」
「マジでチョーサイコー。ゲロ吐くまで飲も飲も」

2. 食べ物

「この食べ物は芸術的で、まさに写真を撮るに値するよな。まあ、ただ単に、俺がいまクソ腹減ってるってだけなのかもしれないけどさ。実際は、たいしたことないんだろうけど」
「ああ、ものすんげーウマそうだ。一生覚えてるだろうな。このマヨネーズポークサンド。我が心の友よ」

3. 風景

「見ろよあの森を。もう感動しかないな。おい、すぐに写真を取れ、マーシャ。その写真を後でどうこうするわけじゃないけど、知ったこっちゃないし、すぐに写真撮ったことすら忘れるけど、そういうもんさ。まあともかく、メモカを滝や山なんかのゴミ写真で埋め尽くそうじゃないか。悪くないだろ」

4. ライブ

「ところで、これは何だい? 見たところ、チカチカ光ってるボケボケの何かの画像のようだが」
「昨夜のライブだよ。僕は、昨日、ライブを生で楽しむかわりに、携帯のクソ品質のカメラで、決定的瞬間を逃さぬように写真を取るのに熱中してたんだ」

5. キス

「僕達の関係がすんげーいいってことを見せつけるために、オットセイみたいに唇をぶつけ合ってる写真をとっておこう」
「オッケー」

6. 車

「珍走団速度まで加速するのに60秒しかかからないんだぜ」

7. 洗面所での自分撮り

[翻訳を諦めた]

相変わらずoatmealだ。ぬこの画像が含まれていないということは評価できる。

2010-10-13

いまだに変な宗教が流行っている

プログラミング :: 高速なプログラムを書く為に :: 初めに

ランタイムとして DLL を使用しない様にしましょう。DLL の設定にすると、 例えば cos や sin 関数を呼び出すのに dll を使用する (本来 CPU の命令 fcos を一回実行するだけの筈) など、 御馬鹿な事になるからです。数値計算に於いて、頻繁に呼び出す基本関数が dynamic link になっているというのは最悪です。

MSVCでスタティックリンクのマルチスレッドのランタイムライブラリを使ってはならない。リソースリークが完全に防げないからだ。DLL版は、DllMainでDLL_THREAD_DETACHを補足することによって、CRTに必要なリソースを開放しているので、リークは起こらない。

そもそも、DLLを使用しない理由というのが、cosやsinというのは、馬鹿げている。/Oiも知らないのだろうか。

/Oi (Generate Intrinsic Functions)

2010-10-12

シカトの語源は花札

「シカト」という言葉がある。意味は「無視」という意味だが、この語源はなかなか面白い。

シカト - 語源由来辞典

花札に由来する言葉で、少なくとも50年の歴史があるらしい。知らなかった。

standard-layoutとlayout-compatible

標準レイアウト(standard-layout)とレイアウト互換(layout-compatible)の条件や、保証されている挙動を詳しく執筆したが、果たして日本人のC++プログラマーのうち何人が、ここまで詳しい解説を望んでいるのだろうかと疑問になった。

実際、この条件と挙動が規格によって保証されているというのは、C++にとって、非常に重要である。つまり、オブジェクトの内部表現に互換性があるというわけで、他の言語とのやり取りにも使える。

しかし、あまりにも厳密な定義は、果たして一般のプログラマーの役に立つであろうか。これらは、多くの場合、「なんとなく動く」とか、「この環境では動く」程度の認識しかされていない。広く一般に、どのような条件を満たせば、どのような挙動が保証されているのかということを把握しているC++プログラマーは少ない。

もちろん、language-lawyerたる私からすれば、全C++プログラマーは、これらの条件と保証される動作を知っておくべきである。そもそも、C++が必要とされる現実的な分野には、これらの挙動には、まずお世話になるはずである。

暗黙のムーブはやっぱやめよう

Implicit Move Must Go « C++Next

暗黙のムーブは深刻な互換性の問題を引き起こすから、削除しようとのこと。

問題点としては、C++03のコードは、暗黙のムーブを考慮せずに書かれてきた。もちろん、暗黙のムーブなんてものは存在しなかったのだから、これは当然である。しかし、以下のような場合、

// well-formedなC++03のコード
// C++0xではill-formed
class C
{
public:
    C() : v(5) { }
    ~C() { std::cout << v[0] << std::endl ; }
private :
    std::vector<int> v ;
} ;

int main()
{
    C a = C() ;
}

C()によって生成される、prvalueの一時オブジェクトは、暗黙のムーブによって、ムーブされる。std::vectorは、ムーブ可能だからだ。しかし、std::vectorをムーブしてしまうと、もはや要素にアクセスすることはできない。しかし、C()によって生成される一時オブジェクトのデストラクターが走る際、メンバーであるvの要素にアクセスしている。これはエラーとなる。

このコードは、C++03ではwell-formedだが、C++0xではill-formedとなる、互換性のないコードである。

やはり、暗黙のムーブは、あまりにも登場が遅すぎたと言わざるをえない。これに対して、いくつか解決方法が考えられた。たとえば、ユーザー定義のデストラクターがあるばあい、暗黙のムーブの生成をしないようにしようというものだ。しかし、その場合でも、やはり互換性の問題がある。ついには、privateなメンバーを持つクラスは暗黙のムーブを生成しないようにしようなどという意見まででてきた。しかし、それでもなお、この問題は解決しない。

というわけで、暗黙のムーブは、残念ながら、ドラフトから取り除くべきだというのが、Daveさんの意見のようだ。ただ、デフォルトのムーブの動作は、なかなか便利なので、例えば = default ;によって、明示的にデフォルト化された場合は、暗黙のムーブを明示的に生成するような機能を残すのもいいのかもしれない、とも言っている。

いずれにせよ、互換性は言語の進化への大いなる障害だと言わざるをえない。言語の普及のためには、どうしても必要なのだが。