4

Mathtextというプログラムを作成しました。このプログラムは、特定の文字範囲を「数学的な文字のような記号」などの Unicode 範囲にシフトしてプレーンテキストのイタリック体、ボールド体、セリフ体などを生成することにより、プレーンテキストに「スタイル」を与えます。

シェルのように行ごとのインタープリターとして機能し、行が入力された後に翻訳された行を出力します。これは、ファイルcat全体を変換するためにファイルを /piped できること、および ^D を押すことで「シェル」を「終了」できることを意味します。これは、stdin が EOF を押すことによって検出されます。

すべてが機能します。ただし、^D を押して終了すると、segfault が発生します。何が原因なのか、いまだによくわかりません。

でコンパイルすると-g -O0少し役に立ちます。^D が押されたときの転置での strlen 呼び出しから問題が発生することがわかりました。ただし、eof が true であるため、^D の間は決して transpose を呼び出すべきではありません。

プログラム受信信号 SIGSEGV、セグメンテーション違反。
__strlen_sse2 () at ../sysdeps/x86_64/multiarch/../strlen.S:31
31 ../sysdeps/x86_64/multiarch/../strlen.S: そのようなファイルまたはディレクトリはありません。
    ../sysdeps/x86_64/multiarch/../strlen.S 内
(gdb) ここで
#0 __strlen_sse2 () at ../sysdeps/x86_64/multiarch/../strlen.S:31
#1 転置の 0x0000000000400b0e (s=0x0, capsDelta=120263, smallDelta=120257, numDelta=0) at mathtext.c:58
#2 main の 0x0000000000400e2b (argc=2, argv=0x7fffffffe4b8) at mathtext.c:92
4

3 に答える 3

3

のほとんどの使用はfeof()バグです。このプログラムは、このメイン ループで完全にそれを示しています。

char temp[1048576];
do {
    if (!strcmp(argv[1], "serifb"))
        transpose(fgets(temp, 1048576, stdin), 119808 - 'A', 119834 - 'a', 120782 - '0');
    else if (!strcmp(argv[1], "serifi"))
        transpose(fgets(temp, 1048576, stdin), 119860 - 'A', 119886 - 'a', 0);
    else if (!strcmp(argv[1], "serifbi"))
        transpose(fgets(temp, 1048576, stdin), 119912 - 'A', 119938 - 'a', 0);
    else if (!strcmp(argv[1], "sans"))
        transpose(fgets(temp, 1048576, stdin), 120224 - 'A', 120250 - 'a', 120802 - '0');
    else if (!strcmp(argv[1], "sansb"))
        transpose(fgets(temp, 1048576, stdin), 120276 - 'A', 120302 - 'a', 120812 - '0');
    else if (!strcmp(argv[1], "sansi"))
        transpose(fgets(temp, 1048576, stdin), 120328 - 'A', 120354 - 'a', 0);
    else if (!strcmp(argv[1], "sansbi"))
        transpose(fgets(temp, 1048576, stdin), 120380 - 'A', 120406 - 'a', 0);
    else if (!strcmp(argv[1], "mono"))
        transpose(fgets(temp, 1048576, stdin), 120432 - 'A', 120458 - 'a', 120822 - '0');
    else if (!strcmp(argv[1], "fullwidth"))
        transposeBlock(fgets(temp, 1048576, stdin), '!', '~', 65281 - '!');
    else return help();
} while(!feof(stdin));

ファイルの終わりでfgets()が返さNULLれ、次の の呼び出しでfeof()true が返されます。したがって、正しいアプローチは、入力関数の戻り値をテストすることです-とにかくそのテストを行っているので、呼び出す必要はありませんfeof()(ファイルエラーとファイルの終わりを区別したい場合を除きます)。

char temp[1048576];
while (fgets(temp, sizeof temp, stdin) != NULL) {
    if (!strcmp(argv[1], "serifb"))
        transpose(temp, 119808 - 'A', 119834 - 'a', 120782 - '0');
    else if (!strcmp(argv[1], "serifi"))
        transpose(temp, 119860 - 'A', 119886 - 'a', 0);
    else if (!strcmp(argv[1], "serifbi"))
        transpose(temp, 119912 - 'A', 119938 - 'a', 0);
    else if (!strcmp(argv[1], "sans"))
        transpose(temp, 120224 - 'A', 120250 - 'a', 120802 - '0');
    else if (!strcmp(argv[1], "sansb"))
        transpose(temp, 120276 - 'A', 120302 - 'a', 120812 - '0');
    else if (!strcmp(argv[1], "sansi"))
        transpose(temp, 120328 - 'A', 120354 - 'a', 0);
    else if (!strcmp(argv[1], "sansbi"))
        transpose(temp, 120380 - 'A', 120406 - 'a', 0);
    else if (!strcmp(argv[1], "mono"))
        transpose(temp, 120432 - 'A', 120458 - 'a', 120822 - '0');
    else if (!strcmp(argv[1], "fullwidth"))
        transposeBlock(temp, '!', '~', 65281 - '!');
    else return help();
}
于 2010-08-31T13:02:47.120 に答える
3

エラーまたは EOF で NULL を返すため、プログラムは NULL を逆参照fgetsしており、結果を単純に使用する転置にこれを直接渡しています。

于 2010-08-31T12:30:27.240 に答える
1

feof未来を予測することはできません。実際に ^D キーを押すまで、それがファイルの終わりであることを知りませんfgets。すべての入力が既に最初に存在するため、ファイルを読み取ってもエラーは発生しません。転置関数で NULL を確認します。

于 2010-08-31T12:43:11.317 に答える