憂鬱な午後のひととき
誰にも邪魔されず集中してコーディング作業が出来た. なんかすかっとした(笑).
組み込み向け某コンパイラ, 優秀なんだが memset() で16KB以上指定すると動かないというバグ(仕様?)
にはちょっと参った. 原因を突き止めるのに苦労したぞ.
ええい, やけにむしゃくしゃしている. プログラムでもして気分を入れ替えよう.
・やはりプロファイルは重要だ. 特に不慣れなアーキテクチャ上では,
プロファイラが無くったって, なんでもいいから実測しないと駄目だなあと再認識した一日であった.
・ファミレスで禁煙/喫煙を聞かれたので禁煙席を望んだら, 散々待たされた挙句まともな分煙をしてないところに案内された.
隣で煙草吸ってるんだもん. というか店全体がそうだった. しきりも換気もないなら分けるなよ.
・引越し作業ほぼ完了. 小中高大に下宿先, と古い建物が多かったので本当に新しい部屋って初めてかも.
思っていたよりもずっとうれしい. そういや大学に行くまで図書館というのは瓦屋根 + 白壁だと思い込んでいたなあ.
・C++の演算子オーバーロードを使いながら計算.
便利なんだけど使いすぎると型変換のうっかりミスが出やすいので加減が難しい.
・一日中コード書きというかコード削除? タイムリミット1週間. 果たして間に合うのか.
・TOWNS がたたいても起動しなくなってしまった. ほんとに困るんだけど. だれか要らない人譲ってくれへんかな.
夕方なんかたるいなと思ったら血圧が上90下65だった. 普段は普通なのに.
・名古屋の友人に会いに行き, ついでに会社も見せてもらった.
近くで食べたお蕎麦屋さんには「蕎麦の風味を損なわないためお茶を出しません」
というような張り紙があったのだけど, その前に禁煙にせえよと思った.
・↓言わずもがなだけど一応補足
"能"の ShiftJIS での2byte目は \ なので次の行と連結してコメントになってしまう.
VC++ で問題なくコンパイルできるソースが ICC7 でコンパイルできない場面に遭う.
10分ほど悩んで "// 分解能" が原因だったことに気がつく.
ICC7 は ShiftJIS に対応してないんか.
漢字サポートのオプションを探したけど見つからなかった. 無いはずはないと思いたいのだけど.
・最近身の回りが (物理的にも) ごたごたしていてなかなか集中できない.
すさんだ心を落ち着けるために『豆つぶほどの小さないぬ』(佐藤さとる)を読み返す.
・初めて株を売った. 指値で1週間ほどほっといたので気がついたら売れていた.
金額の割りに感動が薄い.
下記の C 上での直感に反する演算子の挙動で思い出したけど
例えば C 言語で a = f() + g(); という記述は f() と g() のどちらが先に呼ばれるかは不定だし
int i = 3; i = i++ * i++; は未定義だ(ちなみに VC++ だと 11 になった).
C++ ではしばしば演算子オーバーロードをして (a + b) * (c + d) みたいな使い方をするわけだけど
a + b と c + d のどちらが先に計算されるかは不定になってしまう.
「左から評価される」とか決めるべきじゃなかったのかな.
#それともすでに決まってる?
std::map においてある条件を満たす値のキーを除くときに,
map.erae(itr) したあと ++itr しても不定になるので
itr = map.begin();
while (itr != map.end()) {
if (itr->second がある条件を満たした) {
XXX::iterator tmp = itr;
++tmp;
map.erase(itr);
itr = tmp;
} else {
++itr;
}
}
というコードを書いていたのだけど
itr = map.begin();
while (itr != map.end()) {
if (itr->second がある条件を満たした) {
map.erase(itr++);
} else {
++itr;
}
}
でよいことを昔の
cppllで知った.
map.erase(itr++); と map.erase(itr); ++itr; が違うというのが面白い.
・ICC++ のマイナーバージョンアップ通知.
かなり頻繁にあるのでアップデートする前に次の版が出てしまうこともよくある.
ほったらかしよりはいいんだけどそんなに修正版が出てると逆に信頼できないような.
・下の文字定数領域の話とも関係する
const char**へのキャストの話の続き
// char** から const char** への暗黙の変換が禁止されてる理由
#include <stdio.h>
int main()
{
const char **cp;
char *p[2];
cp = p; // (const char**)キャスト必要
cp[0] = "abc";
p[0][0] = 'X';
printf("cp[0]=%s\n", cp[0]);
return 0;
}
これを C++ ソースとしてコンパイルすればどのコンパイラでもエラーになる. そして Linux 上だと落ちる.
C としてコンパイルすると BCC や gcc や ICC では警告を出し, VC++ や net2003 では警告レベル最大でも何も言わない.
VC++ では実行もできる. ゆるいなあ.
「最近 Windows Update 多いね」という話題から「VC++ だと文字定数領域も書き換えられたよなあ」
との私の発言に, 「それはちゃうやろ」のつっこみが入ったので実験.
#include <stdio.h>
const char *a = "ABC";
int main()
{
char *p = (char *)a;
printf("a=%s\n", a);
p[0] = 'x';
printf("a=%s\n", a);
return 0;
}
の結果は
a=ABC
a=xBC .
ちなみに gcc では実行時に segment fault になった. で, もう少しつっこんでみる.
VC++ のファイルリスティングで asm ファイルを出力させると,
_DATA SEGMENT
??_C@_03KDF@ABC?$AA@ DB 'ABC', 00H ; `string'
_DATA ENDS
てな感じで data セグメントに置かれているので例外が出ないのは当然.
試しに _DATA を CONST に置き換え, MASM でアセンブル(ml /coff /c) & リンクして
実行すると無事例外が発生するようになる.
通常のコードがそうしていないのは何故だろう. 過去との互換性のため?
... おやおや, net2003 では CONST 領域に出力するようになってるが例外は出ない.
言語拡張をオフにすると例外発生. なかなか複雑だ.
[メモ] CreateSemaphore(NULL, 1, 0x7FFFFFFF, NULL) と CreateMutex(NULL, 0, NULL) との違い.
同じスレッド内で二度ロックをした場合, 前者によって作られた mutex はブロックするけど,
後者だと内部カウンタが増えるだけでブロックしない. 後者は Linux の ptherad_mutex_init の
PTHREAD_MUTEX_RECURSIVE_NP 相当.
・小一時間自転車でぶらっとしたら, 直射日光のせいで思ったより体力を消耗した.
・ここ2週間ほどたたいても起動しなかったTOWNSを分解掃除したら復活した.
ありがたい. でもどこまで持つかな.
・『赤ちゃんは顔をよむ』(山口真美)
赤ちゃんが人の顔を認識するのはいつか, 赤ちゃんは何故かわいいのかといった疑問を,
どうやって調べ解明していくのか. まだ読みはじめだけど非常に面白い.
ただ
表紙は内容に対する印象とずれが大きいと思う.
一日中開発環境の設定に手間取ったあげく, 結局うまくいかず疲れた.
見知らぬアーキテクチャ用のコードをVC++@Winで書いて, そちらに送って実行結果を教えてもらう.
これがほんとのリモートデバッグ(苦笑).
・pairingのちょっとした応用を思いついた気がする. うまくいけば研究会で発表できるかな.
・等号比較の箇所でタイプミスして代入演算子になったまま気付かず30分ほど悩んでしまった. 恥ずかしい.
でも昔触ってたコンパイラは警告を出してくれたんだけどなあ.
8月
御意見は光成滋生<herumi@nifty.com>までお願いします