The Man Who Fell From The Wrong Side Of The Sky:2009年1月30日分

[最新版] [一覧] [前月] [今月] [翌月]

2009/1/30(Fri)

[NetBSD] libnbcompat

pwd_mkdb(8)、time_tでなくnbtime_tのようにしてホストのtime_tとは切り離さないとダメな気が。
んで芋蔓でtime.hあたりの関数も以下略、でもそれはさすがにキツイか。
time_tくらいならホストのを使って最終的にserializeする時にターゲットに変換ですかね。
このへん今のlibnbcompatは全くあてにならない、先日mklocale(1) + CHAR_MAXでも
ホストのCHAR_MAXが使われてしまうことに悩み、結局NBCHAR_MAXに書き換えて逃げたと
本人は供述しており動機は不明。

[C言語] iconv(3)が扱うのは文字列ちゅーかバイト列でんがな

ホントは重箱の隅タグが適切だな。

iconv(3)で時々みかけるのが

void
convert(const char *s)
{
	iconv_t cd;
	char *input;
	size_t input_bytes, ret;

	...
	input = s;
	input_bytes = strlen(s);
	ret = iconv(cd, &input, &input_bytes, ...);
	...

ちゅう使い方、 これなんかそうやね(from kbkさんとこ)。
変換元の文字列の長さ判定にstrlen(3)使ってしまっとるのだが
これ変換元のencodingがUTF-16/32とか'\0' != L'\0'である可能性を忘れとるので
誤作動する可能性もある行儀の悪いコードと云わざるを得ない。

変換元の文字コードがnl_langinfo(CODESET)、つまり現在のlocaleの文字コードであることが
100%確実であればstrlen(3)は必ず正しく動くと保障できるので、この限りではありませんが。
(nul-terminateされてないとか初歩的なアレは別ですが)

それと同様に

	...
	output_left = output_size;
	ret = iconv(cd, NULL, NULL, &output, &output_left); /* stateを初期状態に戻す */
	...
	output[output_size - output_left] = '\0';
	...

のように変換後の文字列バッファに対してnul-terminateを付与するコードもありがちですが
これも変換後のencodingがUTF-16/32だったりする可能性を忘れとるわけでして決していいコードではないのよね。

まぁこっちのケースは誤作動することはないし、このoutputをlength checkをせず'\0'で末端を知る関数
例えばstrcpy(3)などに渡したとしてもbuffer overrunを防ぐことはできるという(まぁそんな関数に渡すこと自体
激しく間違ってるわけですが)利点?はあるから許容範囲かもしれない。

これ変換後文字列がnul-terminateされてることを保障したければ変換前文字列をnul-terminateしろ
(そうすればiconvをNULL引数で呼んでstateを初期状態に戻す必要すらない)ちゅうのが大原則なんだけど
部分文字列だったりするとコピーが必要になってしまうし、そもそも変換前の文字コードのnul文字が0x0なのか
{ 0x0, 0x0}なのか { 0x0, 0x0, 0x0, 0x0 }なのか判らん状態だと、手の下しようがないという問題もあるのが困るやね。
だからこれも変換後の文字コードを現在のlocaleの文字コードであることを保障してやって'\0'を使うあたりが落とし所かも。

まぁstr*とmem*の使い分けもままならないレベルのC初心者にiconv(3)は難しいってことで。
コードを読む時に、スラスラと脳内でs/char/byte/の置換ができるようになった上で、用心して使えと。

そもそも文字コード変換なぞ必要のないよう、CSIでアプリを書くことを覚えろといいたいところなんだけど
最近はUTF-8決め撃ちのプロトコルとかも多いのでそうもいかないのが泣き所。
昔はCSIで書けば文字コード変換なんて必要なかったんだけど、今ではそういうDQNの為に
逆に文字コード変換が必須になっちまってるからなぁ、トホホ *1

まぁこの手のサンプルでまず省略されてる(というか誰も理解し切れてないと思われる)エラー時の処理を含めた
iconv(3)のサンプルは この記事の最後にあるやつとか *2xvmwareに同梱のiconv_wrapper.cでも読んでちょ。


*1:まぁその為のiconv(3)なんですが。
*2:これも重箱の隅つつけば、バッファをニバイ、ニバーイする部分でsize_t overflow対策してないとかあるけど
ふつー溢れる前にmalloc(3)とかrealloc(3)の上限値に引っかかるからね…


今日

カッコイイは正義、おいらはコフキコガネとかハナムグリのマットな質感が好き。

マットな質感といえば、ネオブラック仕上げが美しいMinolta XD。
ここんとこASA設定/露出補正ダイヤルの動きがシブいなと思ってたら摺動抵抗体が壊れてたよおい。
具体的にはブラシの下にある白い半円形の板が接着剤剥がれしとる orz

修理見積取ってみた、軍艦部の分解だけで直るけど基本料金17〜18kから。
…うーん中古良品買えてしまう、しゃあねぇ自分で直すか…

ちょうど手元にジャンクの外装ボロボロなXDがあったのでこいつで予行演習してみる。
巻き上げレバー、シャッター速度ダイアル、巻き戻しクランクあたりの解体は簡単なんだけど
アイピースシャッター開閉レバーが外れず悩む、これ隠しネジでもないし引っ張っても抜けないし…

2〜3時間悩んでやっとわかった、これ外側からでなくて内側からネジ止めされてるのか(気づくの遅杉。
同XEは目隠し剥がしてネジを外さないと軍艦部を下ろせなかったので
XDもそうだろうと思いこんでしまったのが失敗だった、触らずそのままでOKということだ。

このジャンク、露出計死んでるヤツをスクリーン部品目当てで確保したやつなんだが
今回バラして各部接点のお掃除したら息を吹き返してしまったぜ。


[ホームへ] [ページトップへ]