Cygwinでスタックサイズが足りなくなった
昨日、Cygwinのshがスタックが足りないなどと言い異常終了するようになった。エラーメッセージは記録し忘れたが、以下のリンク先にある「can't commit memory for stack」というのがそれ。
"cant commit memory for stack" error with perl
このエラーは初めて見たので対処方法がわからなく右往左往したが、結局peflagsコマンドを使い、/bin/shのスタックサイズを倍増することで対処できた。
具体的には、まず/bin/shの現在のスタックサイズを確認する:
% peflags -x /bin/sh /bin/sh: stack reserve size : 2097152 (0x200000) bytes
次に/bin/shのスタックサイズを倍の数値に設定する:
% peflags -x0x400000 /bin/sh /bin/sh: stack reserve size : 4194304 (0x400000) bytes
これにより冒頭の異常終了を回避できた。
正直スタックサイズをこんなに消費する方もどうかと思うが、対処しないと仕事が進まないので仕方なくこのようにした。
FreeBSD portsのdevel/boost-libsが1.45.0のままな件について
http://www.FreeBSD.org/cgi/query-pr.cgi?pr=ports/156253
現状send-prされたものでopenなものはこれだけで、どうもboost 1.46.1へのアップデートを提案したところ関連portで不具合が起き、対処している間にboostのバージョンが上がっていった、と。現在はboostを利用するportの不具合を改善しつつ新しいboostへの対応パッチを用意している感じか。
最新のパッチ(http://alexanderchuranov.com/boost-port/boost-145-to-148-v03.diff)を読むと1.46.1へのアップデートの際に出されたパッチ(http://alexanderchuranov.com/boost-port/boost-1.45-to-1.46.1_attempt05.diff)よりシンプルになってるから、1.49.0への対応もそれほど困難ではないだろう。問題はいつリポジトリに反映されるか、なんだけど、これはもう待つしかないかなあという印象。
そもそもなんでこんなことを調べ始めたかというと、Mac OS X上で書いたboost::randomを使った実装をFreeBSDで実行したらSIGFPEが発生したことが発端。再現サンプルは次の通り:
#include <iostream> #include <boost/random.hpp> int main() { boost::mt19937 gen(static_cast<unsigned long>(time(NULL))); boost::uniform_smallint<uint32_t> dst(0x00000000u, 0xffffffffu); boost::variate_generator<boost::mt19937 &, boost::uniform_smallint<uint32_t> > rand(gen, dst); std::cout << rand() << std::endl; return 0; }
上記コードはuint32_tな値を0x00000000〜0xffffffffの範囲で欲しいというもの。これがboost 1.45.0ではSIGFPEが発生し、boost 1.49.0ならば発生しない。
Mac OS XではHomebrewを使ってboost 1.49.0を、FreeBSDではportを使ってboost 1.45.0をインストールしている。boost 1.45.0でSIGFPEが発生する場所は https://github.com/boost-lib/random/blob/1.45.0/include/boost/random/uniform_smallint.hpp#L120 あたり:
r_base += 1; if(r_base % _range == 0) { // No quantization effects, good _factor = r_base / _range;
経緯の説明は省くが、120行目でゼロ除算が起き例外が発生する。この部分はboost 1.47.0で大きく実装が変更されている。boost公式サイトのリポジトリのログも「Update uniform_smallint」のみで詳細は不明。
そんなこんなでFreeBSD portsで新しいboostをインストールしたいのになぜboost 1.45.0のままなのだろう、と調べ始めた結果がこの記事の前半である。
nested repeat operator + and ? was replaced with '*'
仕事でアセンブリ言語のソース間の依存関係を調べるべく、Rubyでスクリプトを書き、その中で正規表現を使った。その時に出た警告についてメモしておく。
例えば行頭にあるラベルを判別するために:
/^\S+\s+/
と書いた。\S+がラベル、\s+はラベルの直後の空白文字列を表す。その後ラベルはあったりなかったりすることに気付き:
/^(/\S+/)?\s+/
と書いた。さらにラベルは一致はさせるがあとで取り出す必要がないので:
/^(?:/\S+/)?\s+/
と書いた。
ここまで書いてRuby 1.8.7-p72では問題なく動いていたが、先日Ruby 1.9.3-p15へアップグレードしたらnested repeat operator + and ? was replaced with '*'
と警告されるようになった。再現すると:
% ruby -e '/(?:\S+)?/' ruby: warning: nested repeat operator + and ? was replaced with '*': /(?:\S+)?/
こんな感じ。ようは(?:\S+)?
は(?:\S*)
書けるよ、ということを伝えたいのかなと理解した。理解したのはいいが:
/^(?:\S*)\s+/
と書いた場合、ラベルにあたる部分がいかにも「0文字以上の文字列」であるように見えて、やや書いた当初の意図(1文字以上の文字列があったりなかったりする)から外れるような気がする。
しかし上記警告が結構な回数出るのがウザく、なんかもうめんどくさくなってしまい、ヤケで結局のところ:
/^\S*\s+/
と書き直した。ここまで来るとどういう意図で書いたものなのかさえわからなくなりそうだが、警告出されるよりはマシか。
gperfが生成するソースコードの扱いについて
gperfが生成するソースコードの扱いについて、gperf 3.0.4のHTMLやinfoでは"The Copyright of the Output"として説明されている。しかし手元にあるgperf 3.0.1~3.0.3のドキュメントには同様の記述を見つけられなかった。僕自身はgperf 3.0.4での説明と同じ認識(生成物はGPLではなく、入力データと同じ扱い)でいたが、gperf自身のドキュメントに何らかの形で明記されているものと思いこんでた。gperfの公式サイトからたどれるドキュメントにもない。
- http://git.savannah.gnu.org/cgit/gperf.git/plain/doc/gperf.info … 最新版のinfo
- Perfect Hash Function Generator … gperf公式サイトからたどれるドキュメント
僕が上記認識を持ったのはかなり以前のことなので、おそらく、昔から特に明記されることはなく上記の通りの扱いであった、それがgperf 3.0.4でようやく明記されることになった、ということなのだろう。ただ明記されてた方が扱いやすいし他の人に説明しやすいので、これからはgperf 3.0.4を使うようにしよう。gperf 3.0.3からの変更点もそれほど大きくなさそうだし。
- GNU gperf 3.0.4 released … info-gnuに投稿されたgperf 3.0.4リリースのお知らせ