0

main.c という名前の次の c ファイルがあります。

#include <stdio.h>
#include <string.h>

#define NUM_CHAR 20

int main(void) {
    char command_line[NUM_CHAR + 2]; /* Command line string includes the new line character ('\n') and a null character ('\0')  */
    while (1) {
        if (fgets(command_line, sizeof(command_line), stdin) == NULL) { /*This function reads up to sizeof(command_line)-1 characters, or until it encounters the new line character. The function adds '\0' to the end of the array */
            perror("Error: standard function fgets has failed");
            break;
        }

        if (command_line[sizeof(command_line) - 2] != '\n' && strlen(
                command_line) == NUM_CHAR + 1) { /*# of characters (excluding '\n') in command_line is <=num_char iff the condition takes place. */
            printf(
                    "Error: command length must be less than or equal     to %d characters\n",
                NUM_CHAR);
        while (getchar() != '\n') {
        } /* read the remaining characters */
        continue;/* continue with  while(1) loop */
        }

        printf("%s",command_line);

        if (command_line[0] == 'Q') {
            break;
        }
    }
  return 0;
}

次の行を含む input という名前のテキスト ファイル:

 Quit

これは、ターミナルで valgrind を実行した後に得られたものです (プログラムの名前もメインです)。

student@student-VirtualBox:~/workspace/tests$ valgrind --track-origins=yes --leak-check=full ./main < input
==2649== Memcheck, a memory error detector
==2649== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==2649== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==2649== Command: ./main
==2649== 
==2649== Conditional jump or move depends on uninitialised value(s)
==2649==    at 0x8048542: main (in /home/student/workspace/tests/main)
==2649==  Uninitialised value was created by a stack allocation
==2649==    at 0x80484FA: main (in /home/student/workspace/tests/main)
==2649== 
Quit
==2649== 
==2649== HEAP SUMMARY:
==2649==     in use at exit: 0 bytes in 0 blocks
==2649==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==2649== 
==2649== All heap blocks were freed -- no leaks are possible
==2649== 
==2649== For counts of detected and suppressed errors, rerun with: -v
==2649== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 11 from 6)

ちなみに、このコードは最適化をオフ ( -O0) にしてコンパイルしました。2 つの質問があります。

エラーの原因は何ですか: 条件付きジャンプまたは移動は、初期化されていない値に依存しますか?

valgrind がこのエラーの原因となった行の行番号を表示しないのはなぜですか?

4

1 に答える 1

2

fgetssizeof(command_line)が に正確にバイトを書き込むという保証はありませんcommand_line。ユーザーが短い文字列を入力した場合、チェック

command_line[sizeof(command_line) - 2] != '\n' 

command_lineあなたのコードによって初期化されていないか、によって書き込まれなかった部分を読み取りますfgets

これを修正するには、いくつかの方法があります。

strlenの終わりを逆参照する前に最初にテストできますcommand_line

if (strlen(command_line) == NUM_CHAR + 1 &&
    command_line[sizeof(command_line) - 2] != '\n')

command_lineまたは、宣言時にすべてを初期化できます

char command_line[NUM_CHAR + 2];
memset(command_line, 0, sizeof(command_line));
于 2013-08-03T11:22:18.103 に答える