タグ

ブックマーク / yupo5656.hatenadiary.org (8)

  • Linux Memory Overcommit - memologue

    かなり昔ですが、或日さんのSolaris8におけるmemory over commitの話題に触発され、Linuxの場合について調べた事があります。正しさは保証しませんが当時のメモを貼っておきます。 memory overcommit? メモリ資源の非常に限られた環境でLinuxを使用しているとよく遭遇する現象なのだが、kernel 2.4までのLinuxでは、"mallocが成功を返したにもかかわらず、その確保した筈のメモリ領域にアクセスすると、SIGKILLによってkernelから強制終了させられてしまう" という現象が 発生することがある。これは、「全プロセスがnew/mallocしたメモリの総量」に対して物理メモリ量が少なすぎる瞬間に於いては常に発生し得る。 何に困っているかといえば、C++でオブジェクトをnewした時に、メモリの枯渇をstd::bad_alloc例外送出という形で

    Linux Memory Overcommit - memologue
  • RAIIもどき in C __attribute__((cleanup(fn)))

    gccの__attribute__((cleanup(fn))) が便利すぎる件について。 C++でコードを書くときは、RAIIとか呼ばれているイディオムを使えば、ご存じの通り、ロックしたmutexを手動で開放する必要もないですし、newしたオブジェクトを手動でdeleteする必要もないです。 void Baz::boo() const { boost::mutex::scoped_lock lock(mutex); // ... return; // lock変数のデストラクタで自動開放。手動での開放不要 }でもC言語だと、当然ながら手動で開放しないといけません。複数箇所でreturnしている場合など、タイプが面倒臭すぎ。 int foo() { pthread_mutex_lock(&mutex); // ... if (hogehoge) { pthread_mutex_unlock

    RAIIもどき in C __attribute__((cleanup(fn)))
  • UNIX上でのC++ソフトウェア設計の定石 (3) - memologue

    鉄則3: マルチスレッドのプログラムでのforkはやめよう マルチスレッドのプログラムで、「自スレッド以外のスレッドが存在している状態」でfork*1を行うと、さまざまな問題を引き起こす可能性があります。「問題」の典型例としては、子プロセスのデッドロックが挙げられます。問題の詳細を把握しないまま、マルチスレッドのプログラムで不用意にforkするのはやめましょう! 何が起きるか 実例から見てみましょう。次のコードを実行すると、子プロセスは実行開始直後のdoit() 呼び出し時、高い確率でデッドロックします。 void* doit(void*) { static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&mutex); struct timespec ts = {10, 0}; nanoslee

    UNIX上でのC++ソフトウェア設計の定石 (3) - memologue
  • memologue - UNIX上でのC++ソフトウェア設計の定石 (2)

    鉄則2: シグナルハンドラで行ってよい処理を知ろう sigaction関数で登録したシグナルハンドラで行ってよい処理は非常に限定されている 次の3つの処理だけが許されている 自動変数の操作 “volatile sig_atomic_t” 型の大域変数の操作 「非同期シグナルセーフ」関数の呼び出し これ以外の処理を記述しないこと! 説明: シグナル受信時に何らかの処理を行うためには、シグナルハンドラと呼ばれる関数を用意し、それをsigaction関数でシグナル名と紐付けておけばOKです。しかし、シグナルハンドラ内で行ってよい処理は、上記の通り非常に限定されています。これを把握しないまま奔放なコードを書くと次のような現象が起き得ます: 問題1: プログラムがデッドロックする危険がある タイミングに依存する、再現困難なバグの原因となる デッドロックの発生が典型例だが、それ以外にも関数の戻り値不正

    memologue - UNIX上でのC++ソフトウェア設計の定石 (2)
  • g++ exception handling - memologue

    Code Project という有名サイトに、VC++の例外処理方法に関する記事があります (http://www.codeproject.com/cpp/Exceptionhandler.asp) が、そこにg++の例外処理方法を解説したコメントがありました。 ざっくりと次のような事を言っています(翻訳してるわけではないので詳しくは英文読んでください)。 g++は、VC++とはちょっと違うやりかたで例外処理を実装している。g++の場合、実際に例外がthrowされない限りは、try/throw/catchを使ったコードを書いてもランタイムのコストはかからない。 foo()がbar()を呼んでいて、bar()が例外を投げるとせよ。このとき、foo()はスタックに戻りアドレス*1を置いてからbar()を呼ぶ。この戻りアドレスを仮にXとする。 このときコンパイラは、 (X, 掃除コードのアドレス

    g++ exception handling - memologue
  • type punning と strict aliasing - memologue

    /.JのGCC-3.4リリースの話題を追っていたら、GCC3では-O2で-fstrict-aliasingが有効だから注意せよというポスト(http://slashdot.jp/comments.pl?sid=175355&cid=537217)があった。 strict aliasing については、Radium Software Developmentさんが詳しい。これは気にしておいたほうがよさそうだ。GCCの -fstrict-aliasing の説明は次。 コンパイルされている言語に適用可能な別名規則(aliasing rule)のうち最も厳密なものをコンパイラが前提することを許します。これによって、 C(およびC++)では式の型に基く最適化を動作させることになります。例えば、ある型のオブジェクトが別の型のオブジェクトと同一アドレスに位置することは、それら2つの型がほとんど同一でない

    type punning と strict aliasing - memologue
  • memologue - __attribute__((init_priority(N))) で、C++のグローバル変数の初期化順序を制御する

    g++の __attribute__)((init_priority(N)))( なる機能の日語の解説が見当たらないので、いつものように紹介文を書いてみます。これは、C++のグローバル変数の初期化順序を制御するためのGCCの拡張機能(attribute)です。 ごく短い説明 動的な初期化が必要なC++のグローバル変数の定義に__attribute__)((init_priority(N)))(をくっつけると、.oファイル上で、その変数の初期化関数(コンストラクタ等)のアドレスが.ctorsではなく.ctors.M セクションに入ります。M は左0パディング5桁固定の数値で、M = 65535 - N です。あとは、shinhさんの2005/11の記事を。特に、リンカスクリプトのSORTのとこに注目、これにより初期化順がinit_priorityで指定した通りになります。Nが小さい程先に初

    memologue - __attribute__((init_priority(N))) で、C++のグローバル変数の初期化順序を制御する
  • 2004-09-09

    googleから私の日記に、localtime_r や strtok_r, getpwnam_r などのキーワードで飛んでくる方が結構多いので、ちょっと関連する話題を書いてみます(内容の割に長い…)。 さて、8/9の日記で、POSIXのlocaltimeという関数(下記)を取り上げ、 struct tm *localtime(const time_t *timer); この関数を複数のスレッドが同時に使うと処理が破綻すると書きました。また、この関数はシグネチャが腐っているので、libcの外側でmutexを使っても処理の破綻を回避することはできず、localtime_rという代用関数を使うしかないとも書きました。POSIXで示されている代用関数(TSF)の一覧は、8/21の日記に書いた通りです。 日は視点をちょっと変えてみて、「localtimeのシグネチャは当にダメダメなのか?」に焦点

    2004-09-09
    tyru
    tyru 2009/08/27
  • 1