ここはバグじゃない? のページ

  • (by K, 2006.02.20)

  • 本のプログラムでおかしいところを見つけたら教えてください(ご協力をお願いします)。
    • (例)初版・第1刷のp.631(29-2)で関数tek_getsizeがstrncmpを使うのはおかしくてmemcmpを使うべきではないか思うのですが、バグではありませんか?
    • 確認できたら下記に載せます(バグフィクスは大規模修正になることが多いので、次の刷があっても反映はできません)。
    • わざと残している不具合も多少はあるので、それについては指摘されても詳細な修正案を示しません。
  • OS以外(たとえば開発ツールなど)のバグ報告はimpressionsへ。
  • 実機での起動がうまくいかない問題に関する話題は、Athlon64X2でお願いします。

  • 初版・第1〜4刷のp.631(29-2)で関数tek_getsizeがstrncmpを使うのはバグでした。どうもすみません。正しいプログラムを以下に載せます(bug0000:初版・第5刷以降で修正されました)。 -- K 2006-02-20 (月) 13:00:53
  • 初版・第1〜4刷のp.670(30-4)で、指定されたファイルが見つからなかった場合の処理を書き忘れていました。どうもすみません。修正案を以下に載せます(bug0001:初版・第5刷以降で修正されました)。 -- K 2006-02-22 (水) 18:41:17
  • 初版・第1刷のp.604(28-3)でmemman_free_4kとするべきところをmemman_freeとしているのはバグでした(2ヶ所あります)。どうもすみません。お詫びして訂正いたします(bug0002:初版・第2刷以降で修正されました)。 -- K 2006-02-27 (月) 11:21:33
  • bug0000のheader宣言の内容が本と違いますが、ここも変更ですか? -- マーボ 2006-03-05 (日) 12:37:45
  • ご指摘ありがとうございます。そこは変更しません。bug0000を書くときに間違えてしまいました。直しました。重ねてすみません。 -- K 2006-03-05 (日) 13:00:15
  • 初版・第1〜2刷のharib19gのa_nask.nasの _api_openwin は、EBXのPUSH/POPが抜け落ちていました(直前のharib19fや直後のharib20aでは直っている)。これはPUSH/POPをするのが正しいのでお詫びして訂正いたします(bug0003:初版・第3刷以降で修正されました)。 -- K 2006-03-06 (月) 22:00:25
  • 初版・第1〜3刷のp.380(19-1)のcmdline[x]のファイル名をs[y]に直すforの中の「if (cmdline[x] == '.') {」を「if (cmdline[x] == '.' && y <= 8) {」に修正します。これによりファイル名にピリオドを含んでいる場合の挙動が改善されます(bug0004:初版・第4刷以降で修正されました)。 -- K 2006-03-25 (土) 18:13:42
  • 初版・第1〜3刷のp.412(20-6)の関数cmd_appだと、「winhelo30」と入力してもwinhelo3.hrbが起動できてしまうという問題がありました。これはバグではなく仕様だといってしまえばそれまでですが、ごくわずかな修正でこの問題を解決できるので、バグとして修正したいと思います(bug0005:初版・第4刷以降で修正されました)。 -- K 2006-03-26 (日) 03:29:55
  • ↑の修正に関連している箇所なので、ついでに質問させて頂きます。file_search() でピリオドが2つ以上含まれているファイルをエラーにしないのは仕様、ということで宜しいでしょうか。先ほど見てみたら個人ページの方にコメントが入っていました。失礼しました。 -- killer_elf 2006-03-26 (日) 16:02:14
  • 質問ありがとうございます。はい、仕様です。それもついでに直すことはできるのですが、修正が出版社の許容範囲を超える(行数の増減がありすぎる)or無理に1行にまとめると汚くなる、ので当初の予定通り、本書のサンプルとしては複数のピリオドもエラーにはしないことにしています(例:「type make..bat」)。 -- K 2006-03-26 (日) 16:05:08
  • 初版・第1〜4刷の30-1のcalcには、 calc 100-10-1 を91と答えてしまうバグがありました。これは 100-(10-1) と解釈してしまうのが原因で、つまりは演算子の優先順位(というか同順位時の結合方向)の判定ミスです。これを修正するにはp.653〜654のif文中の「 && priority >= 」を「 && priority > 」に修正します(計10ヶ所)。以上、お詫びして訂正いたします(bug0006:初版・第5刷以降で修正されました)。 -- K 2006-04-08 (土) 18:09:00
  • 12_day\harib09g\timer.cのtimer_settime関数ですが、66行目でtimerctl.using++;をしてしまうとusingがMAX_TIMER個になるとき、timerctl.timers配列の次の4バイトを上書してしまわないでしょうか? -- まさ 2006-05-07 (日) 21:16:57
  • ご指摘ありがとうございます。確かにそんな気がします。 timerctl.using++; のタイミングが適切ではないようです(bug0007:初版・第6刷以降で修正されました)。 -- K 2006-05-08 (月) 16:31:14
  • 「harib27f」において、ウィンドウが表示されていない状態でF11キーを押下すると、マウスカーソルが消える現象を確認しました(初版−第2刷のCD)。「bootpack.c」のF11キーが押下された場合のロジックで、可視シート数をチェックしていないため、マウスと背景のシートが入れ替わってしまう様です。もう一度F11キーを押下すると元に戻ります。もしかするとわざと残しているバグなのかもしれませんが、よろしくお願いいたします。 -- rapper 2006-08-13 (日) 12:09:19
  • ご報告ありがとうございます。これからちょっと忙しくなるのであとで確認します。 -- K 2006-08-13 (日) 15:21:55
  • rapperさんが発言したことで色々実験したら、その他のバグ?が見つかりました。ウィンドウをすべて消し、F11を押すとマウスが消えますよね、そのあとで、コンソールを出すと、操作が出来なくなります。実験したのは、初版第六版のHarib27fをQEmu上で動かしたときです。 -- mac 2006-08-22 (火) 18:01:40
  • rapperさん、macさんへ。確認しました。これはバグです。初版・第1〜7刷のp.495のリスト部分の今回の改変個所を以下のように修正します。どうもすみませんでした(bug0008:初版・第10刷以降で修正されました)。 -- K 2006-08-24 (木) 19:06:48
  • 初版・第5刷のP401 file_search関数ですが、finfo->name[0]はfinfo[i].name[0]だと思います。最初のファイル名しか見ていませんよね・・・。間違ってたらすいません! -- tanaka 2006-09-30 (土) 02:39:04
  • tanakaさんへ。ご指摘ありがとうございます。そこは確かにおかしいです。バグを見つけてくださってありがとうございました。初版・第1〜7刷のp.401のfile_search()の「finfo->name[0]」の部分は「finfo[i].name[0]」の誤りでした。お詫びして訂正いたします(bug0009:初版・第10刷以降で修正されました)。 -- K 2006-09-30 (土) 12:42:42
  • あっきぃさんが、はりぼて起動直後にコンソールを閉じて、どれでもいいからキーを押すと、OSが動かなくなってしまうというバグを見つけました。初版・第1刷〜8刷のp.571のプログラムを次のように修正します(bug0010)。 -- K 2006-11-10 (金) 16:40:58
  • window.cのvoid change_title8関数のループをまわして色を変えるとなんとボタンの灰色まで青色になってしまっています。ループの中のelse ifを} else if ( (c == tbc_old) && (y < 5) || (y > 18) || (x < xsize - 21) || (x > xsize - 6) ) {にすると直りました。 -- T 2007-04-01 (日) 10:28:06
  • それはバグではありません。青と灰の2色以外の色を指定しないことを前提に作っています。もちろんTさんの目的にはそわなかったのでTさんがそのように改造するのはいいことです。それと以後の指摘の際は他の皆さんと同様に版・刷・ページを明確にしてください。 -- K 2007-04-02 (月) 07:12:09
  • FF11アトルガンの秘宝を攻略しる! www.rmtfcne.com/f11 -- 真夏ノ雪 2007-12-19 (水) 17:27:29
  • 02_day/helloos4/ipl.nasの58行目「0x7dfeまでを0x00で埋める」は「0x7dfeの一つ前までを0x00で埋める」ではないでしょうか。 -- 名無しさん 2008-01-18 (金) 19:29:55
  • ここはプログラムの間違いを指摘するところなので、以後はmistakesにお願いします。・・・そしてご指摘の件についてですが、「〜まで」という語句はあいまいな表現なので、0x7dfeを含むとも含まないとも取れるのではないかと思います(文脈によって)。この場合、名無しさんの理解のとおり「含まない」のが正しいです。技術書なので「以下・以上・未満・超」など厳密な語句を使用するべきだったかもしれませんが、表現が硬くなりすぎることを嫌い、さらにここは厳密にしなくても言いたいことは十分に伝わると思い、本文のとおりとなりました。ご了承ください。 -- K 2008-01-21 (月) 20:46:28
  • p.56の10シリンダ読み込むとき、1シリンダなら問題がなくても2をこえるとQEMUがストップしてしまいます。 -- tasukete 2011-04-28 (木) 21:29:12
  • 申し訳ありません。どうやらCDを使わず作っていたので、CDのものに差し替えたら動きました。レジスタの問題みたいでした。すみません。ご迷惑をおかけしました。 -- tasukete 2011-04-29 (金) 15:41:20
  • langmode設定後(28-7)以降、langmodeが、0・1 -- yoshi 2011-06-26 (日) 20:34:12
  • の場合は問題がないのですが、2(EUCモード)にするとtype haribote.sysなどを行った場合、コンソールの左下になぜか白い四角が出てきます。これはバグでしょうか? -- yoshi 2011-06-26 (日) 20:36:03
  • 僕もyoshiさんと同じことになります。ちなみに初版第16刷です。 -- taka 2013-08-19 (月) 12:13:02

コメントお名前NameLink

bug0000

  • 初版・第1〜4刷のp.631(29-2)の関数tek_getsize(tek.cの一部)
    int tek_getsize(unsigned char *p)
    {
        static char header[15] = {
            0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x4f, 0x53, 0x41, 0x53, 0x4b, 0x43, 0x4d, 0x50
        };
        int size = -1;
        if (memcmp(p + 1, header, 15) == 0 && (*p == 0x83 || *p == 0x85 || *p == 0x89)) { /* ココ! strncmp→memcmp */
            p += 16;
            size = tek_getnum_s7s(&p);
        } /* memcmpはstrncmpの仲間で、文字列中に0があっても指定された15文字まで比較する関数 */
        return size;
    }
    
  • ここで出てきているmemcmpはstrncmpによく似た関数ですが、文字列中に0x00が含まれていても、それで文字列の終わりだとは判断しないで、必ず指定された文字長まで比較するところが違います。今回はheaderの途中に0x00を含んでいるので、strncmpによる比較では不十分でした。お詫びして訂正いたします。
  • memcmpも #include <string.h> すると使える関数なので、#include部分を修正する必要はありません。
  • 初版・第5刷以降で修正されました

bug0001

  • 初版・第1〜4刷のp.670(30-4)の関数HariMainの一部(gview.cの一部)
        /* ファイル読み込み */
        i = api_fopen(p); if (i == 0) { error("file not found.\n"); } /* ココ! */
        fsize = api_fsize(i, 0);
        if (fsize > 64 * 1024) {
            error("file too large.\n");
        }
        api_fread(filebuf, fsize, i);
        api_fclose(i);
    
  • api_fopenに失敗した場合の処理を書いておかないと誤動作の危険がありました。お詫びして訂正いたします。
  • 初版・第5刷以降で修正されました

bug0005

  • 初版・第1〜3刷のp.412(20-6)の関数cmd_appの一部(console.cの一部)
    int cmd_app(struct CONSOLE *cons, int *fat, char *cmdline)
    {
        struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
        struct FILEINFO *finfo;
        struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT;
        char name[18], *p; /* ココ!([13]→[18]) */
        int i;
    
        /* コマンドラインからファイル名を生成 */
        for (i = 0; i < 13; i++) { /* ココ!(8→13) */
            if (cmdline[i] <= ' ') {
                break;
            }
            name[i] = cmdline[i];
        }
        name[i] = 0; /* とりあえずファイル名の後ろを0にする */
    
        /* ファイルを探す */
        finfo = file_search(name, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
        if (finfo == 0 && name[i - 1] != '.') { /* ココ!(&&以降を追加) */
            /* 見つからなかったので後ろに".HRB"をつけてもう一度探してみる */
            name[i    ] = '.';
            name[i + 1] = 'H';
            name[i + 2] = 'R';
            name[i + 3] = 'B';
            name[i + 4] = 0;
            finfo = file_search(name, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
        }
    
  • 8文字より長いアプリ名を入れても先頭8文字だけを切り出してアプリを実行するようになっていましたので、上記のように修正します。またファイル名の最後をピリオドにすると、.HRBの付加を試さなくなります(なんとなくそういう機能があるほうがよさそうに思ってついでにつけました)。
  • 初版・第4刷以降で修正されました

bug0007

  • 初版・第1〜5刷のp.248(12-7)の関数timer_settime(timer.cの一部)
    void timer_settime(struct TIMER *timer, unsigned int timeout)
    {
        int e, i, j;
        timer->timeout = timeout + timerctl.count;
        timer->flag = TIMER_FLAGS_USING;
        e = io_load_eflags();
        io_cli();
        /* どこに入れればいいのかを探す */
        for (i = 0; i < timerctl.using; i++) {
            if (timerctl.timers[i]->timeout >= timer->timeout) {
                beark;
            }
        }
        /* うしろをずらす */
        for (j = timerctl.using; j < i; j--) {
            timerctl.timers[j] = timerctl.timers[j - 1];
        }
        timerctl.using++; /* ココに移動 */
        /* あいたすきまに入れる */
        timerctl.timers[i] = timer;
        timerctl.next = timerctl.timers[0]->timeout;
        io_store_elfags(e);
        return;
    }
    
  • timerctl.using++; の位置を変えました。
  • 初版・第6刷以降で修正されました

bug0008

  • 初版・第1〜9刷のp.495(24-1)の関数HariMain(bootpack.cの一部)
    void HariMain(void)
    {
        (中略)
    
        for (;;) {
            (中略)
            if (fifo32_status(&fifo) == 0) {
                (中略)
            } else {
                (中略)
                if (256 <= i && i <= 511) { /* キーボードデータ */
                    (中略)
    /* ココから */   if (i == 256 + 0x57 && shtctl->top > 2) {  /* F11 */
                        sheet_updown(shtctl->sheets[1], shtctl->top - 1);
    /* ココまで */   }
                    (中略)
                } else if (512 <=i && i <= 767) { /* マウスデータ */
                    (中略)
                } else if (i <= 1) { /* カーソル用タイマ */
                    (中略)
                }
            }
        }
    }
    
  • && shtctl->top > 2 を書き足しました(F11のところ)。
  • 初版・第10刷以降で修正されました

bug0010

  • 初版・第1〜8刷のp.571(27-2)の関数HariMain(bootpack.cの一部)
    void HariMain(void)
    {
            (中略)
            if (sht->bxsize - 21 <= x && x < sht->bxsize - 5 && 5 <= y && y < 19) {
                /* 「×」ボタンクリック */
                if ((sht->flags & 0x10) != 0) {
                    (中略)
                } else {    /* コンソール */
                    task = sht->task;
                    sheet_updown(sht, -1); /* とりあえず非表示にしておく */
    /* ココから */  keywin_off(key_win); key_win = 0;
                    if (shtctl->top > 1) {
                        key_win = shtctl->sheets[shtctl->top - 1];
                        keywin_on(key_win);
                    }
    /* ココまで */  io_cli(); fifo32_put(&task->fifo, 4); io_sti();
                }
            }
            (中略)
    }
  • 本の内容に対する修正個所を「ココから」「ココまで」で示しています。
  • 本での修正では行数を増やせないので、いくつかの行がマルチステートメント(=;のあとに改行せず、次の命令を書いている)になっています。読みやすくするために普通に改行を入れても動作に違いはありません。

リロード   新規 編集 差分 添付   トップ 一覧 検索 最終更新 バックアップ   ヘルプ   最終更新のRSS
Last-modified: 2013-09-01 (日) 14:17:01 (2290d)