hoge diary - November 2006

November 28, 2006

[雑記] プリズン・ブレイク

2006 年 12 月 2 日からプリズン・ブレイク (英題: Prison Break) の vol.8 〜 12 の DVD がレンタル開始だそうです.

このドラマは今月 9 日の夜中に日テレで放送(この日は所用で東京に居ました)されていた第 6 話を偶然観ただけなのですが,それだけで全部まとめて観たい! なんて思ってしまいました.というわけでそのうちレンタル屋で借りてくることにします.

November 24, 2006

[雑記] Solid State Society

今日ようやく攻殻機動隊 STAND ALONE COMPLEX Solid State Societyの DVD が手元に届きました.

スカパーのパーフェクトチョイス160で放送されてから 3 ヶ月も経ってますね.スカパーを視聴していない私は DVD を買うかレンタルするかしないと観られなかったわけですが,これでやっと観られるようになったわけです.

パッケージの外観および中身を携帯のカメラで撮影したものを載せておきます.こんな感じでした.

Solid State Society Package 正面 (正面)

Solid State Society Package 外袋開封 (外袋開封)

Solid State Society Package 中身取り出し後 (中身取り出し後)

ゆっくり鑑賞させて頂くことにします.

November 12, 2006

[C++] 参照で例外を捕まえる

More Effective C++ 日本語版の 65 ページに参照で例外を捕まえるという項があります.初めてここを読んだときは驚きました.この本に書かれている通り,例外オブジェクトを値渡しすると,スライシングが発生する上に 2 度コピーコンストラクタが呼び出されるので,できれば参照で渡したいと思っていました.しかし,関数ローカルな例外オブジェクトを参照で渡してもいいのだろうか,という疑問も同時に浮上.

夜も眠れぬくらい非常に気になったので,その分の睡眠時間を削って,手近な環境(g++-4.1.1, i686-pc-linux-gnu)でテストしてみることに.

以下の簡単なコードでテストします.

class E {
public:
    int a;
    E() { a = 0x64; }
};

int func1() { throw E(); }

int main() {
    int a = 0;
    try { func1(); }
    catch (E& e) { a = e.a; }
    return 0;
}

これを g++ -O0 でコンパイルした後にリンクして,でき上がった ELF を逆アセンブルした結果が次の通りです.ただし,_fini などの余分な関数は除いています.

080485c0 <_Z5func1v>:
 80485c0:       55                      push   ebp
 80485c1:       89 e5                   mov    ebp,esp
 80485c3:       53                      push   ebx
 80485c4:       83 ec 14                sub    esp,0x14
 80485c7:       c7 04 24 04 00 00 00    mov    DWORD PTR [esp],0x4
 80485ce:       e8 dd fe ff ff          call   80484b0 <__cxa_allocate_exception@plt>
 80485d3:       89 c3                   mov    ebx,eax
 80485d5:       89 d8                   mov    eax,ebx
 80485d7:       89 04 24                mov    DWORD PTR [esp],eax
 80485da:       e8 75 00 00 00          call   8048654 <_ZN1EC1Ev>
 80485df:       c7 44 24 08 00 00 00    mov    DWORD PTR [esp+8],0x0
 80485e6:       00
 80485e7:       c7 44 24 04 1c 87 04    mov    DWORD PTR [esp+4],0x804871c
 80485ee:       08
 80485ef:       89 1c 24                mov    DWORD PTR [esp],ebx
 80485f2:       e8 f9 fe ff ff          call   80484f0 <__cxa_throw@plt>
 80485f7:       90                      nop

080485f8 <main>:
 80485f8:       8d 4c 24 04             lea    ecx,[esp+4]
 80485fc:       83 e4 f0                and    esp,0xfffffff0
 80485ff:       ff 71 fc                push   DWORD PTR [ecx-4]
 8048602:       55                      push   ebp
 8048603:       89 e5                   mov    ebp,esp
 8048605:       51                      push   ecx
 8048606:       83 ec 24                sub    esp,0x24
 8048609:       c7 45 f4 00 00 00 00    mov    DWORD PTR [ebp-12],0x0
 8048610:       e8 ab ff ff ff          call   80485c0 <_Z5func1v>
 8048615:       eb 2e                   jmp    8048645 <main+0x4d>
 8048617:       89 45 e8                mov    DWORD PTR [ebp-24],eax
 804861a:       83 fa 01                cmp    edx,0x1
 804861d:       74 0b                   je     804862a <main+0x32>
 804861f:       8b 45 e8                mov    eax,DWORD PTR [ebp-24]
 8048622:       89 04 24                mov    DWORD PTR [esp],eax
 8048625:       e8 b6 fe ff ff          call   80484e0 <_Unwind_Resume@plt>
 804862a:       8b 45 e8                mov    eax,DWORD PTR [ebp-24]
 804862d:       89 04 24                mov    DWORD PTR [esp],eax
 8048630:       e8 8b fe ff ff          call   80484c0 <__cxa_begin_catch@plt>
 8048635:       89 45 f8                mov    DWORD PTR [ebp-8],eax
 8048638:       8b 45 f8                mov    eax,DWORD PTR [ebp-8]
 804863b:       8b 00                   mov    eax,DWORD PTR [eax]
 804863d:       89 45 f4                mov    DWORD PTR [ebp-12],eax
 8048640:       e8 5b fe ff ff          call   80484a0 <__cxa_end_catch@plt>
 8048645:       b8 00 00 00 00          mov    eax,0x0
 804864a:       83 c4 24                add    esp,0x24
 804864d:       59                      pop    ecx
 804864e:       5d                      pop    ebp
 804864f:       8d 61 fc                lea    esp,[ecx-4]
 8048652:       c3                      ret
 8048653:       90                      nop

MASM ユーザな私には AT&T 記法は読みづらいので,ここでは逆アセンブル結果を得るために objdump -m i386:intel としています.

さて,main 関数から見てみます.まず最初にスタックフレームの作成とローカル変数の初期化をやってますね.その直後に _Z5func1v (func1 関数) をコールしてます.

_Z5func1v に移って,スタックフレームを作り... その直後に (アドレス 0x80485c7で) GOT 経由で __cxa_allocate_exception を呼び出してます.

この関数は何かというと... libstdc++ に含まれている,以下のような関数です.ここでは関数名を一部改変し,エラー処理を全て省略して示しています.

void* __cxa_allocate_exception(std::size_t thrown_size) throw()
{
  void *ret;

  thrown_size += sizeof (__cxa_exception);
  ret = malloc (thrown_size);

  __cxa_eh_globals *globals = __cxa_get_globals ();
  globals->uncaughtExceptions += 1;

  memset (ret, 0, sizeof (__cxa_exception));

  return (void *)((char *)ret + sizeof (__cxa_exception));
}

見ての通り,例外オブジェクト用のメモリ(投げるオブジェクトのサイズ + sizeof(__cxa_exception))をヒープ上に確保しています.

その後で __cxa_throw を call しています.この call 命令の後ろには func1 関数に対応する ret 命令がないことから,__cxa_throw を呼び出した時点で main 関数の catch 節に制御が移るということになります.

その main 関数では他にもいろいろと例外処理に関する関数が呼ばれていますが,今回の目的は例外処理の全貌を解析することではなく,例外オブジェクトを参照で受け取ってもよいかどうかの調査ですので,これ以上調べなくても大丈夫でしょう.念のため,class E のコンストラクタと main 関数の catch 節の両方でそれぞれ例外オブジェクトのポインタの値を出力し,両者が一致していることを確認しました.

結局,ソースコードの上では関数ローカルに見えるオブジェクトが,実はヒープ上に確保されている,ということです.謎は解けました.これで安心して眠り... もとい,参照で catch ができます.めでたしめでたし.

VC の場合はどうなってるのかも気になるところです.また機会があればそのうち...

November 4, 2006

[Gentoo] Beryl を開発版スナップショットからダウングレード

何の気なしに Beryl 関連パッケージのバージョンを開発版スナップショットから 0.1.1 にダウングレードしたところ,スプラッシュスクリーンが綺麗に出るようになりました.あと,ウィンドウの透明度も正しく表示されるようになりました.

というわけで,現在インストールしている Beryl 関連パッケージのバージョンは以下の通りです.

  • beryl-0.1.1-r2
  • beryl-core-0.1.1
  • beryl-plugins-0.1.1-r1
  • beryl-dbus-0.1.1-r1
  • beryl-manager-0.1.1
  • beryl-settings-0.1.1

[Gentoo] 真っ白なウィンドウ in AIGLX

AIGLX を使用中に突然,ウィンドウが真っ白になってしまう現象が起こったので調べてみると,HOWTO XGL/Troubleshooting - Gentoo Linux Wiki に書いてありました.が,実行してみるも効果はなく,いろいろ試行していると,どうやら当方の環境ではインストールしている Mesa を media-libs/mesa-6.5.2_pre20061102 から media-libs/mesa-6.5.1-r1 にしたところ現象が治まりました.

[Gentoo] Xgl から AIGLX に戻す

glxinfo を実行したときに direct rendering: No と言われるのが気になるので,AIGLX に切り替えました.AIGLX だと Beryl のスプラッシュスクリーンが綺麗に表示されませんが,これは我慢することに.

AIGLX の状態で glxinfo を実行すると,direct rendering: Yes と表示される代わりに以下のメッセージが表示されます.

libGL warning: 3D driver claims to not support visual 0x5b

とりあえず目立った問題がないので無視することに.

November 3, 2006

[Gentoo] 再び Xgl (AIGLX + Beryl + Aquamarine) を試す

前回のインストールから約 2 ヶ月.もう一度 Xgl をインストールしてみることにしました.

前回とは違い,compiz-quinnstorm が Beryl という名称になっています.あと,KDE 用の window decolator (Aquamarine) が登場していました.これはいい感じです.

例によって Gentoo Linux WikiGentoo Linux Wiki を参考にします.

後者を読んでいくうちに分かったのですが,どうやら当方の環境の場合,Xgl でなく AIGLX を有効にした X.org で十分そうです.

というわけで,まずはインストールから始めます.

layman を使って,xeffects の ebuild を取得します.

# layman -a xeffects

次は,/etc/portage/package.keywords/etc/portage/package.unmask を変更します.

# cat >> /etc/portage/package.keywords <<EOF
=x11-wm/beryl-0.1.1-r1 ~x86
=x11-wm/beryl-core-9999 -*
=x11-plugins/beryl-plugins-9999 -*
=x11-plugins/beryl-dbus-9999 -*
=x11-misc/beryl-manager-9999 -*
=x11-misc/beryl-settings-9999 -*
=x11-apps/xlsclients-1.0.1 ~x86
=x11-libs/libwnck-2.16.1 ~x86
=x11-wm/aquamarine-9999 -*
EOF
# cat >> /etc/portage/package.unmask <<EOF
x11-wm/aquamarine
EOF
#

そして X.org と Beryl のインストールです.X.org は既に 7.1 をインストールしていましたが,ちょうど aiglx という USE flag が新たに追加されていたので,それを有効にしてもう一度関連するパッケージを emerge することにします.

# vim /etc/make.conf
(USE="aiglx" を追加)
# emerge -puD --newuse world (関連パッケージの再 merge)
# emerge beryl

無事に完了したら,/etc/X11/xorg.conf を編集します.

Section "ServerLayout"
        Option          "AIGLX"                 "True"
EndSection

Section "Device"
        Option          "DRI"                   "True"
        Option          "XAANoOffscreenPixmaps" "True"
EndSection

Section "dri"
        Group           0
        Mode            0666
EndSection

Section "Extensions"
        Option          "Composite"             "True"
EndSection

さらに,ログイン時に Beryl が起動するようにします.Gentoo Linux Wiki では,KDE を使用している場合は /etc/env.d/99kde-env もしくは /etc/env.d/*kdepaths* を書き換えるように書いてあります.さて,私は Aquamarine を使いますので,どうやら起動スクリプトを書く必要があるようです.スクリプトのファイル名は /usr/local/bin/aquamarine-start とでもしておきます.

#! /bin/sh

beryl --replace &
exec aquamarine --replace

スクリプトには実行属性を与えておきます.

# chmod 755 /usr/local/bin/aquamarine-start

あと,Gentoo Linux Wiki に書いてある通りに "dbus" 引数付きで beryl で起動すると以下のように落ちてくれます.

$ beryl --replace dbus
XGL Absent, assuming AIGLX

beryl: SmcOpenConnection failed: Could not open network socket
Pop:
Old number of plugins is 0.
Plugin dbus is a new plugin.
Plugin settings is a new plugin.
New number of plugins is 2.
Checking for new plugins.
Seeking to load dbus.
beryl: Couldn't load plugin 'dbus'

segmentation fault
$
("dbus-launch beryl --replace dbus" としても同じように落ちます)

プラグイン dbus がロードできないと言われてます.プラグインファイル(/usr/lib/beryl/libdbus.so)はちゃんと存在しているので,ファイルが見つからなかっただけ,というオチではなさそうです.ただ,あまり深く調べるのも面倒なので,こっちの環境に何らかの問題があるんだろうなぁ,と思いつつ,今回は dbus 引数を外して起動します.

さて,起動してみましょう... 再び感動の瞬間です.

スクリーンショットはありませんが,Aquamarine のおかげで KDE 側で設定したウィンドウ装飾がちゃんと使えています.あと,2 ヶ月前とは違い,突然 X サーバが落ちる,といった現象も見られませんでした.

ただ,AIGLX を使っているせいか,Beryl のスプラッシュ画面が綺麗に表示されない(部分的に真っ黒に潰れたような表示 (以下))ので,試しに Xgl もインストールしてみました.

Beryl 0.1.1

# emerge =xgl-0.0.1_pre20061020-r1

Gentoo Linux Wiki に従い,/etc/X11/gdm/gdm.conf を Xgl 用に合わせて書き換え,GDM を再起動し,あとは普通にログインするだけです.

Beryl のスプラッシュスクリーンが綺麗に表示されました.めでたしめでたし.


Valid XHTML 1.1! Valid CSS!
© 2004-2009 ぱくちゃん.
Last modified: Tue Jan 09 03:23:50 JST 2007