トップ 最新 追記

日々の破片

著作一覧

2016-09-04

_ ハードコアプログラマのためのハードコアプログラミング入門書

アスキーの鈴木さんからC++によるプログラミングの原則と実践をいただいた。うれしい。

重さ1.9Kg、厚さ4.5cm、ページ数1200越え、お値段は7000円だ。

さすがに、こうなると、今更(おれは既にプロフェッショナルなのだ)おれが自分で購入する本ではない。読み切れないのがわかっているからだ(金額については「今更」ということはなく、むしろ今のほうが手に届くので別の話となる)。

まず、きちんとしたネガティブな評価を見ておこう。

幸い、同じアスキー(ではなくドワンゴのほう)の江添さんが「およそ悪書の見本のような本だ」という完全読破されたうえで結論を出されている。

おれはストラウストラップではないのでどうでも良いのだが、しかし一応、あるべき反論は少ししておこう。

「文章は簡潔にすべし」→それは違う。この本は仕様書ではなく、

・何よりも教科書

・次善として熱心な独習者の学習書

なのだ。

あらゆる方向から現在のトピックについて考察し言及し説明し明確にすることで、読者にそのトピックについて基礎的な概念を根付けたうえで学際への端子を用意し、考察の発展への可能性を生む。むしろそうでなければならない。

冗長性(特に「脱線」)は反復からくる退屈さを多少軽減し、客観的であるものを多少なりとも主観的に軸足をずらすためのテクニックだ。さらに反復は退屈さも生むが、反面、記憶への焼き付け効果ももたらす。考えながら読むには冗長性は不可欠とも言える。

本書を教科書として採用する先生は、少なくとも自覚のうえでストラウストラップには経験も知識も考察も気力も一歩譲るはずだ。であれば、講義のためのネタとして含まれる冗長さはむしろ望ましい。それは独習者にとってもそうであり、特に「自問自答の文章」は、それをドライブするには欠かせないものだ。

「サンプルコードの1割ほどがコンパイルできない」→しかしストラウストラップは達人ではない。達人はそもそも研究者にも先生にもならずに実務を行う。

(以下、『達人プログラマー』P.101の「書籍の執筆」をネタに延々とストラウストラップに対してお説教がはじまるのだが、現実問題として、これは本当に悩ましい問題なのだ)

というわけで、事前に、タイポがたくさんあるとわかっていれば間違い探しをしながらコンパイルしてください。

エディター上でコードを記述しているときは適切と考えた名前が書籍(実際は同じくテキストかも知れないしTeXかも知れないしWordかも知れないが)として「読む」と非常に不適切に思えて修正したくなることはある。これは断言できる。プログラムのコンテキストと書籍のコンテキスト(本文とのレイアウト上のバランスのような、プログラミングではあり得ない要素が含まれてくるからであり、部分抽出となるためにコードでの説明に追加をしたくなるのだ)は異なるのだ。驚くべきことだが。そこでつい手を入れてしまい、ここで再抽出-再コンパイル-再実行(テスト)しないと、まず100%間違える。多忙なストラウストラップが、この罠に陥ったとおれは推測するが、まず間違いないだろう。

「文字コードへの理解がない」→原書には存在しない第28章「C++と日本語対応」という江添さんその人の手による補章で補償してある。(ただ、ストラウストラップ自身の理解がどうかについてはwchar_tの限界程度で特に他のプログラミング言語よりもC++がひどいとも思われないので判断は留保する)

本書は、誰のためのものではないかはわかっている。

少なくともWebフロントエンドプログラマーのための本ではない。確かに1200ページを読む時間的投資と7000円の金銭的投資は無駄になるだろう(短期的には)。

しかし、下から上まで、プログラミングのフルスタックプログラマーを目標とするのなら、まったく無駄ではない。むしろたかだか7000円と教師について1年、著者によればまじめに独習して3か月(でも足りない)で、手に入るものはあまりに巨大だ。

この日記の題にも書いたが、本書はC++の入門書ではない。あくまでもプログラミングの入門書なのだ(言語としてC++を利用している)。入門書である以上は読んですぐ実践に使えるわけではない。しかし必要な概念(と周縁領域の知識)はほぼすべて得られる(20世紀レベルでは、と入れないとちょっと不誠実だな。でも並行、並列、分散は別の話だと思う)。とんでもない網羅性を持つゆえの厚さと重さなのであった。

まずは目次を見よ。と書き出すのが面倒なのでアスキーのページを示したら、章題しか出てないや。小見出しレベルが重要なのだが。

でも、0章(ここはストラウストラップの真摯な態度に感銘を受けるとても良い章なので立ち読みだけでもしておきたいところ)に目次を無視してストラウストラップ自身が本書で学べる内容について箇条書きしている。こちらを引用しよう。

本書では、効果的かつ実用的なプログラミングを行うために最低限必要な概念、手法、ツールを示したいと考えている。これには以下のトピックが含まれる。

・プログラムの構成

・デバッグとテスト

・クラスの設計

・計算

・関数とアルゴリズムの設計

・グラフィックス(2Dのみ)

・グラフィカルユーザーインターフェイス(GUI)

・テキストの操作

・正規表現マッチング

・ファイルおよびストリーム入出力(I/O)

・メモリー管理

・科学技術計算

・設計とプログラミングの理想

・C++標準ライブラリ

・ソフトウェア開発戦略

・C言語のプログラミング手法

(最後とその2個前はまあしょうがないかなぁ。「2Dのみ」とわざわざ限定しているところが上に書いた20世紀っぽさの自覚がある点かも知れない。「設計とプログラミングの理想」に刮目せよ)

(多分続く)

C++によるプログラミングの原則と実践(Bjarne Stroustrup)

(おれは逆にこのサイズだと紙の書籍のほうが読みやすいと思うが、そうは言っても重いし厚い。ディスプレイが2面あるのなら、片面にEmacs(コンソールとvimでも良いけど)、もう片面に本書というのもありではなかろうか。というわけで達人出版の電子書籍版もリンク)

#(コメントでメタテキストを始めるマークなのだが、マークアップ記法では……という小ネタをどこかで見かけたが忘れた)江添さんの

このことから、私たちはとても重大な教訓を得た。

というユーモアは好きだ。


2016-09-08

_ C++によるプログラミングの原則と実践

ハードコアプログラマのためのハードコアプログラミング入門書の続き、ちょっとだけ。

まず、間違いの指摘。

P.62 本文1行目「文(§4.4.1.1)を使用することで」

→「if文(§4.4.1.1)を使用することで」

昼の本業のほうでいろいろ考えることがあって、それはつまりいかにユーザーストーリーをテクニカルタスクに落とすか、つまりは手続きをシステム的に構成可能なものとするかについての、人による極端な差というものについてだ。

『C++によるプログラミングの原則と実践』は、そうとうに(考え方が)古典的な書籍だと思うのだが、結局のところは、本書の1章(前ふりのパートの最後)と2章(プログラミングの初歩の最初)でストラウストラップが書いていることこそが、重要なのだ。

1章は、次から次へと、身の回りのどこにコンピュータがあり、どこにソフトウェアがあり、どう役に立っているかについて、ちょっと幼児向けの乗り物図鑑を彷彿させるところがある、いわゆる「気づき」のための章となっている。

2章は、Hello worldなのだが、章末の練習問題2が端的だ。

本章で学んだことを応用し、コンピューターが2階のトイレを探し出すための命令からなるプログラム(§2.1)を記述する。(略)

もちろん、これを額面通りに受け取って、まだC++でそんなものは書けないよ! と読者に言わせるための問題ではない。

2階のトイレを探すという処理を、命令に分解しろという問題なのだ。(関数型プログラミングの世界ではないことはわかる)

ちゃんとした先生について練習問題を解けば、一連の箇条書きがまず作成され、そこから共通部分がくくりだされ、あるいはループが見つかり、もし古典的なプログラムがお好みであれば構造化されたプログラムとなり、もしロボット目線で書くのであれば、比較的古典的なオブジェクト指向プログラムとなる。

この訓練が全然ない開発者がいることに驚くわけだが、少なくとも本書は、まずそこから入っている。コンピュータのように考えて、コンピュータのための命令を作る。

ちなみに変数は箱型モデルでの説明だが、C(C++)の変数は確保されたメモリ領域(として説明してあるから、抽象的な箱というわけではない)(とはいえ最適化で消え失せることもあるが、それは本書のレベルでは知ったことではない)に名前をつけたものとして説明しているので、このプログラミング言語では正しい。

・というわけで抽象度は低いわけだが、なんか安心して読めるんだな、これが。

C++によるプログラミングの原則と実践(Bjarne Stroustrup)


2016-09-11

_ ポケモンGOに見る中堅企業の人事戦略

さて、中堅企業の人事担当なわけだが(ということにする)、何しろ中堅どころなので社員教育に配分するリソースがない。そこで、採用面接のときに手数料を徴収するようにした。とはいえそれほど悪辣なことはしたくないので、面接に要するコストとして辛うじて赤にならない程度のものだ。

手数料には社会人教育(名刺の受け渡しだの、ビジネスメールの書き方だのどうでも良いことなのに、他社との関係で必要となるもの)用のもの(これを飴と呼ぼう)と、労働者としてのスキルアップの技能教育用のもの(これを星の砂と呼ぼう)の2種類を徴収する。どういう仕組みかわからないが、お祈りメールを書くとお礼に飴が1個余分にもらえることになっている。

採用面接には新卒(進化前)と中途(進化後)が来る。

新卒はたいていレベルが低いので伸びしろが見えない。そこでIQとかEQとかいう良くわからないが個人の資質を担当部課のリーダーに判断させる。なぜかこれは正確無比で「芸術的」だの「戦力外」とかジャッジできる。

一方、中途には何をしていたのか全然レベルが低いやつと、やたらとレベルが高いやつの両方が来る。これについてもリーダーが芸術的だの戦力外だのジャッジするわけだが、即戦力性を重視するのでそれほど参考にはしない。

しかし、リソースには限りがある。したがって、中途についてはレベルが高くて高技能持ちについては即採用して実務に投入する。しかし戦力外とされた者については使い捨てにする。つまり、リソース(星の砂)を振り向けたりはしない。ボロボロになったり、ビジネス状況が変化したら、リストラだ(なぜか、このときも飴が1個もらえる)。

「はい次の方」

「新卒のコイキング、CP10です。悪あがきが得意です」

「(小声で隣のリーダーにきく)彼はどうかな?」

「なんと、芸術的です。特に問題解決能力は測定不可能」

「とはいっても、CP10ではなぁ。スキルアップ資金を出せないよ。というわけで、お祈りします」

「はい次の方」

「中途のウツボット。CP1500。ソーラービームが使えます」

「おお、素晴らしい。明日から来てくれたまえ」

「(小声でリーダーがささやく)ちょっと、あれは実戦は難しいですよ」

「何、全体レベルが2000越えになったら辞めてもらうさ」

「はい次の方」

「新卒のタマタマ、CP600です」

「うーん、特技はサイコキネシスなんだね……」

「(リーダーが小声で)ちょっとちょっと、芸術的ですし、CP600ですし、進化すれば(なぜかこの人は社会人研修をこう呼ぶ)ソーラービームを使えるようになるかも知れませんし、絶対採用すべきですよ!」

「内定出します!」

「はい次の方」

「中途のシャワーズ、CP78、ハイドロポンプの免許持ってます!」

「どうかなリーダー、なかなか見どころがある若者ではないか」

「確かに、芸術的ですし、問題解決能力、人材育成能力ともに測定不可能。しかし、わが社のリソースでは彼をCP2000にまでもっていくに足る砂がありません」

「お祈りします」

時たま、紹介でやって来るものもいる(これを金の卵、銀の卵、銅の卵と呼ぶ)。紹介なのでいきなり戦力外ということはない。

「紹介で来ました、ラプラスです!」

「はい採用!」

「紹介で来ました。イーブイです!」

「微妙だなぁ……、どうかなリーダー?」

「芸術的ですし、もしかしたら大文字を覚えたブースターになるかも知れないので採るだけ採ったらどうでしょう? 教育してから判断しても良いかと」

「明日から来てください」

「紹介で来ました。金の卵のカイロスです!」

「お祈りします!」

「そりゃ乱暴な(と、リーダー)。CP1000越えてますし、カビゴン商事に対する斬り込み隊長には十分使えますよ!」

「では、明日から来てください」

「新卒のポッポ来ました。CPがなんと320あります!」

「またポッポか。お祈りします」

「ちょっと待った(とリーダー)。飴が死ぬほど余っているから、とりあえず2回研修受けさせて、翼で打つと暴風を覚えたら正式採用ということで。ナッシー通商を落とすには十分かと」

「インターンしてみますか?」

という具合である。


2016-09-12

_ C++によるプログラミングの原則と実践(続)

なんか精読し始めたら止まらなくなってしまった(ぱらぱら読むのではだめだなぁ)。

この本は抜群に優れているではないか。さすがだぜストラウストラップ。

というわけで、続き

第3章の練習問題4は間違っている。

誤)「整数値を1つ入力させるプログラムを記述する」

正)「整数値を2つ入力させるプログラムを記述する」

第4章の「コンピュテーション」はおそらく白眉だ。ストラウストラップ自身が最後のところで、ここで語り尽したみたいなことを書いている(まあ、意味は、プログラムの意味ということについてだけだが)。

しかし惜しいかな、いきなり重要なところを誤訳している。

P.83 4.2.

多分誤)「正しく効率のよいプログラムは複雑であり」

こうでなければおかしい)「正しく効率のよいプログラムであっても複雑過ぎれば」

重要な主張はプログラマーの仕事を、「計算を次のように表現することだ」と順位付けしている点にある。

・正しく(プライオリティーNo.1)

・単純に(プライオリティーNo.2)

・効率よく(プライオリティーNo.3)

したがって、複雑さよりも単純さを尊ぶ。よくわかる。

そしてP.84がすばらしい。引用する。

正確さ、単純さ、効率のよさに関心を抱くのは、コードを他人のために記述し、それをうまく行うことに責任を負った瞬間だ。つまり、プロになることを決意したら、その責任を負うのは当然のことだ。

いや、本当に、この言葉をすべてのくそコードの山をひり出した連中にのしをつけて送りつけてやりたい。

これこそが肝要ではないか。

ここからP.85まで、つまり、4.2.「目的とツール」は毎日お題目として唱えさせたいくらいだ。

P.105の4.5.1.関数を使用する理由は、正しいが、今となっては弱弱しい。

この理屈(計算の論理的な分割、名前によりコードが明確化、プログラムを複数の場所から利用可能、テストが容易)の3番目を軽く凌駕する、「最近のエディターを使えば、コピー&ペーストというものが使えるのですよ? いつの時代の紙テーププログラマーorパンチカードプログラマーですか?」というごみな見解を覆すことは難しいだろう(そういう了見の連中は、論理的な分割は能力的にできないし、名前を持たないし、テストをしないからな)。

だから、関数化(モジュール化と言い換えても良い)には、もっと積極的な理由が必要なのだと考えるが、このあたりが良識的で優秀な著者の限界というものだろう。

P.117。バグ。言及していないbegin()およびend()についての問題と用語への掲載がある。おそらく元はイテレータを利用していたのを、「:」を利用したイテレーションに書き換えたことに追随していないのではないかと推測する。

C++によるプログラミングの原則と実践(Bjarne Stroustrup)

clangで本書の例やサンプルをコンパイルするには

clang++ -std=c++11 ファイル名

とする。


2016-09-18

_ バトル用ポケモンの組み方

現在のジム状況はCP2000越えのカイリューやカビゴンが主流となっている。

ここで問題となるのは、相手チームのジムに対する攻撃ではなく、自チームのジムに対する道場破りだ。(相手チームはとにかく全滅させれば良いので、こちらも高CPのカイリューを用意してひたすらタコ殴りすれば良い)

例として、レベル3で既に3頭が置かれている自チームのジムに自ポケモンを配備する場合を考える。

素の状態のレベル1のジムの名声は1000、レベル2のジムは2000、レベル3のジムは4000なので、これを8000に持ち上げればレベル4となり、自ポケモンが置ける。

今、ジムにはCP500のカメール(多分、置いてみたかったのだろう)、1900のギャラドス、2000のシャワーズがいるとする。

ここで、CP2800のカイリューで殴り込みをかけてタコ殴りで突破したとする。

この場合、得られる名声はたかだか350とかそんなものだ。というのは、どうも倒した場合の名声(これは得られるXPの10倍に相当する)は、最後に倒した相手ポケモンのCPを自ポケモンのCPで割った数に500を乗じたものだからだ(と断言してよいかは知らないけど、FBで読んだ河合さん(面識ないから良くわからないけど、友達の友達なので読めているのだと思う)の投稿から。確かにそういう結果になる)

ということは、2000/2800*500≒357

なので、XPは35、名声は+357で、さっきまで4000だったものが4357になる。あと何回タコ殴りすれば良いのだろうか?

ここで、手元にCP1500のサンダーズがいるとする。

カメールもギャラドスも水ポケモンなので、頑張れば2人抜きはできる可能性がある。最後のシャワーズは出てきた瞬間に降参するのがミソ(ただし、元気のかけらといい傷クスリのペアが、すごい傷クスリよりも多ければ、降参せずに倒されたほうがむしろ良いとか、持ち物のストックによって多少戦略が変わる。基本はスピード重視なのでさっさと降参するほうが良い)

この場合、

1900/1500*500≒633

となり、XPは63、名声は+633でさっきタコ殴りで4357になった名声が一気に4990になった。あと5回サンダーズが頑張れば名声が8155になる(得られるXPは315)。

CP2000が主流である以上、CP1300~1500で相性が良く連打が効くか強力な一発技を持つ中堅層を保持しておくと実によいことになる。

というわけで、以下が対自チームジム戦の現在の主力だ。

・2000CPのギャラドス(ラッキーなことに龍の息吹と龍の波動持ち)→3000CPカイリュー(いきなりこいつが留守番しているジムもそこそこある。が、多いのは2000CPカイリューなので得られるXPも名声もそれほどではないことが多い)を結構倒せる(ただし破壊光線や龍の波動を回避できれば)

・1500CPのかみなりサンダーズ(かっては対相手チームバトルの主役だったが、全体のCPが上がった結果、ベンチを温めることが多かったが、ここに来て復活)→CP2000前後のギャラドス、シャワーズ用(ハイドロポンプを回避できれば勝てる)

・1500CPの地震サイドン(よりも技1が格闘なのがでかい)→CP2000前後のカビゴン(破壊光線を回避できれば勝てる)

・1500CPのソーラービームウツボット→CP2000前後のギャラドス、シャワーズ用

・1300CPの暴風ピジョット→2000CP以下のナッシー(ソーラービームは比較的回避できるが、タネ爆弾持ちにはたいていやられてしまうのが難)

・1500CPのハイドロシャワーズ→2000越えのブースターやウィンディ(大文字1回受けても余裕で勝てる。が、シャワーズが大技を「避けた」するときはくるっと実に優雅にバク転するので、これが見たくて回避動作をさせることも多い)

というわけで、技は比較的重要だが、それ以上に種族相性がもっと重要だということでした。

まとめると対相手チームジムバトルではなく、対自チームジムバトルにおいては、低CP高バトル能力+技相性戦略が重要というのが結論。


で、これを応用して仲間でやるのであれば、あえてCP高いが無能(個体値ではなく、技1と2がしょぼいやつ)なやつにジム番させて、交互に倒してXP稼ぎながらジムレベルを上げまくって、全員の高CPポケモンを投入すれば(空きができ次第投入すれば良いわけだが、最初に配備させたへなちょこよりも低CPだと意味がない)、難攻不落のバベルの塔ができるのだが、そういうそびえたつジムは今のところ見たことがない。

とにかくCPが2/3~1/2程度のポケモンが余裕で倒せるへなちょこ(あるいは低HP)は、飴にするよりもそのほうが有効だと思う(カイロスとかアズマオウとかがお勧め(追記:と書いたが(後のほうで書いているドリルライナーのアニメがおもしろいと書きたかったためにちょっと現実を捻じ曲げてしまった)、こいつら2000にするのはもったいないが、素で1000くらいだとCP500の中途半端なやつでバトルすることになって、それはそれで今度は勝つのが難しい。竜巻ギャラドスあたりが狙い目かな)。ちなみにアズマオウのドリルライナーは回避が簡単なわりには見た目が面白いので一度は配備してバトルするとおもしろいと思う)。


2016-09-19

_ Visual StudioでclangでC11を試す(が)

C11のAppendix Kを試してみたくて、bash on Windowsのclangで次のコードをコンパイルした。

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
int main()
{
    char tmp[80];
    int n = scanf_s("%s", tmp); // => コンパイルエラーとなる
    if (n > 0) {
        puts(tmp);
    }
}

するとscanf_sは未定義だと警告され、結局はリンクエラーとなる。

test.c:(.text+0x1e): `scanf_s' に対する定義されていない参照です

/usr/include/studio.hを見たら、確かに定義が存在しない。

まあAppendix Kはオプションだからそんなものかも知れない。

でも待て、Visual Studio 2015 - Clang with Microsoft CodeGenなら行けるのではないか? と考えた。

というのは、clang with MS CodeGenでclang用に追加されるincludeディレクトリはC:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\ClangC2\includeで、ここにはstdio.hは存在しないからだ。

つまり、stdio.hはVC++のヘッダを共通で利用することになる。

で、コンパイルすると、無事コンパイルが成功する。

……いや、コンパイルが成功するのは期待する動作ではない。

期待する動作は、VC++がそうするようにコンパイルエラーとなることだ。

VC++は上記のソースをコンパイルすると次のエラーを吐く。

test.c
test.c(8): warning C4473: 'scanf_s': 書式文字列として渡された引数が不足しています
test.c(8): note: プレースホルダーとそのパラメーターには 2 の可変個引数が必要ですが、1 が指定されています。
test.c(8): note: 不足している可変個引数 2 が書式文字列 '%s' に必要です
test.c(8): note: この引数はバッファー サイズとして使用されます

で、予想されるように、clangでコンパイルしたプログラムは実行できて、かつ動作は予想できない。バッファサイズを与えていないから何文字入力できるか不明だし、とりあえず山ほど入力すれば0xC0000005で死ぬ。

これはちょっとひどいのではないか? まだ、scanf_sは未定義といって怒るほうが1000億倍ましだ。

もちろん以下のように書き直すと、期待通りに動作する。

#define __STDC_WANT_LIB_EXT1__ 1  // <= これ結局本当におまじない以上の意味が無いということだな
#include <stdio.h>
int main()
{
    char tmp[80];
    int n = scanf_s("%s", tmp, (unsigned)sizeof(tmp)); // x64でも通るようにするには(unsigned)キャストが必要(size_tではない)
    if (n > 0) {
        puts(tmp);
    }
}


2016-09-25

_ たのしいムーミン一家

かれこれ10年以上前に子供からおもしろいから読めと言われて渡されたまま放置していた『たのしいムーミン一家』を読んだ。あっという間だった。TwitterのTL見ると12:17頃に読み始めて14:16には読了しているから2時間くらいか(途中昼飯食っているはずだから映画1本90分という感じかな)。

冒頭でいきなりスナフキンがムーミントロールと一緒に冬眠に入るところで驚いた。ムムリク族はもう少し人間なのかと思っていた(人間世界も旅しているから公園のエピソードとかあるわけだろうからもっと人間に近いと思い込んでいたのだ、海のトリトンが卵に驚くところみたいだな)。

で春が来て目が覚めて読み始めたが、噂には聞いていた通りに非常にシニカルなところがあり、妙なニヒリズムありで、実に楽しい。お互いに毒づきながら楽しく愉快に暮らしているところが、心地よいのだな。

最後の大団円の頓智や、その前のどれだけ恐ろしいことが起きるのかと思うと、とっても紳士な態度をとるところとかも良い感じだ。そのあたりでうまさにしびれたのは、ジャコウネズミの願いを真に叶えてしまうところだ。というか、スノークのお嬢さんが驚くほど俗っぽいところと、ムーミンママが世界をルールしているところとか、ヘムリンさんが子供と同じ立ち位置にいるところとか、読まなきゃ知らないまま終わっていただろうところがいちいちおもしろい。全世界の切手を集め終わると、収集家ではなくコレクションの持ち主に進化してしまって少しもおもしろくないというのは良い感覚だなと思った(部屋の中で1番賢くなるなってやつに1脈通じるものがある)。

堪能しまくりの約2時間だった。

たのしいムーミン一家 (新装版) (講談社青い鳥文庫)(トーベ・ヤンソン)

(読んだのは元の版のほう。気ちがいみたいにという形容が出て来てちょっとどきどきした(くらいにPCに訓致されている)が、新装版では修正されているのじゃないかな)

解説にフィンランドの主となる民族はアジア系(トーベヤンソンはそれに対してスェーデン系ということはアーリア民族ってことだろうが)だとあるけど本当なのかな?


2016-09-30

_ コマンドラインプログラムのライブラリ化

何か問題があると、すぐさまexit(n)とかで抜けてしまうプログラムをライブラリにしなければならず、いろいろ弱ったが、考えてみればそのための大域脱出だった。

たとえば元のプログラムが

#inculde <stdio.h>
// ...
int fatal(char* tmpl, ...)
{
  va_list argp;
  ...
  vprintf(tmpl, argp);
  exit(4);
}
void do_extract(char* src, char* dst)
{
   ...
}
int main(int argc, char* argv[])
{
    if (!strcmp(argv[1], "extract")) do_extract(argv[2], argv[3]);
    else if (...
}

だった場合、

#include <setjmp.h>
static jmp_buf env;
int fatal(char* impl, ...)
{
  va_list argp;
  ...
  vprintf(tmpl, argp);
  longjmp(env, 4);
}
int do_extract(char* src, char* dst)
{
   int exitcode = setjmp(env);
   if (exitcode) return exitcode;
   // 元の処理
   return 0;
}

で、問題はもしこのライブラリを呼び出すプログラムが延々と動作する場合で、かつライブラリの中でmallocやfopenをしまくると、巻き戻しがされないことだ。

その場合は、jmp_bufをスタックにすれば良いのかな?

static int ijmp = 0;
static jmp_buf env[32];
int fatal(char* impl, ...)
{
  va_list argp;
  ...
  vprintf(tmpl, argp);
  longjmp(env[--ijmp], 4);
}
void memallocfn()
{
    char* mem = NULL;
    int exitcode = setjmp(env[ijmp++]);
    if (exitcode) 
    {
        free(mem);
        longjmp(env[--ijmp], exitcode);
    }
    mem = malloc(BUFF_SIZE);
    if (!mem) fatal("can't allocate memblock (%d) %d", BUFF_SIZE, errno);
    ...
    free(mem);
}

2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|10|11|

ジェズイットを見習え