Ошибка сегментации со спринтом - PullRequest
0 голосов
/ 25 марта 2012

Я создаю makefile создатель, но я застрял в этой ошибке на sprintf, самое любопытное, что у меня есть несколько sprintf перед тем, с ошибкой, и они работают нормально.

Воткод:

if ( WIFEXITED(stat)  ){

    if ( WEXITSTATUS(stat) ) {

        if ( cFiles == 0 && cFolders == 0 ) {
            Crear(path);
        }

        cFolders = 1;
        TEMP = malloc( sizeof(char)*( strlen(direntp->d_name) + 25 ) );

        if ( TEMP == NULL ) {
            perror("Malloc Error: ");
            exit(1);
        }

        if ( sprintf(TEMP, "\n%s/%s.a: force\n\t$(MAKE) -C %s\n",direntp->d_name, direntp->d_name, direntp->d_name) < 0 ) {
        perror("Sprintf Error: ");
        exit(1);
        }

        write(STDOUT_FILENO,TEMP,strlen(TEMP));
        f.name = malloc( sizeof(char)*( strlen(direntp->d_name)*2 + 3 ) );

        if ( f.name = NULL ) {
            perror("Malloc Error: ");
            exit(1);
        } 
            //This is the one with the problem!!!       
            if ( sprintf(f.name, "%s/%s.a", direntp->d_name, direntp->d_name) < 0 ) {
            perror("Sprintf Error: ");
            exit(1);
        }

        l = AddToList(l,&f);
    }
}

Ответы [ 4 ]

1 голос
/ 25 марта 2012

Не похоже, что вы выделяете TEMP достаточно большим

TEMP = malloc( sizeof(char)*( strlen(direntp->d_name) + 25 ) );

должно быть:

TEMP = malloc( sizeof(char)*( strlen(direntp->d_name)*3 + 25 + 1 ) );

Вы печатаете d_name три раза, и вам также необходим дополнительный байт для нулевого терминатора.

Аналогично, в этой строке:

   f.name = malloc( sizeof(char)*( strlen(direntp->d_name)*2 + 3 ) );

должно быть

   f.name = malloc( sizeof(char)*( strlen(direntp->d_name)*2 + 3 + 1) );

для учета нулевого терминатора.

Использование таких утверждений может помочь убедиться в правильности ваших расчетов:

    int TEMP_size = strlen(direntp->d_name)*3 + 25 + 1; 
    TEMP = malloc(sizeof(char)*TEMP_size);

    if ( TEMP == NULL ) {
        perror("Malloc Error: ");
        exit(1);
    }

    if ( sprintf(TEMP, "\n%s/%s.a: force\n\t$(MAKE) -C %s\n",direntp->d_name, direntp->d_name, direntp->d_name) < 0 ) {
      perror("Sprintf Error: ");
      exit(1);
    }
    assert(strlen(TEMP)+1==TEMP_size);
0 голосов
/ 25 марта 2012

Некоторые заметки в дополнение к предыдущим ответам:

  1. Большинство современных Unix-подобных систем имеют asprintf () и vasprintf () в стандартной библиотеке, которая выделяет буфер самостоятельно. Использовать их проще, чем вычислять необходимый размер, распределять и вызывать sprintf (), даже если они перераспределяются немного.

  2. Заполнение буфера и его последующая печать в стандартный вывод с использованием write () выглядит бесполезным осложнением по сравнению с простым printf (). Использование stdio для таких задач намного лучше, если только вы не используете то, что stdio не может стабильно обрабатывать (например, неблокирующий ввод / вывод).

  3. Задача, которую вы выполняете, намного лучше вписывается в некоторый язык сценариев (Perl, Python, Tcl, Ruby и т. Д.), Если только некоторые внешние странные обстоятельства не заставляют вас использовать C; Предполагается, что C в Unix выполняет области ближе к ядру и низкому уровню. Смотрите, например «Искусство программирования Unix» для рассуждений.

0 голосов
/ 25 марта 2012

Вы не выделили достаточно памяти для этого спринта:

sprintf(TEMP, "\n%s/%s.a: force\n\t$(MAKE) -C %s\n",direntp->d_name, direntp->d_name, direntp->d_name

Вы выделяете sizeof (direntp-> d_name) +25, но я вижу 25 символов + 3 * sizeof (direntp-> d_name) +1 дополнительный символ (ваш \ 0, указывающий конец вашей строки)

привет

0 голосов
/ 25 марта 2012

"% s /% sa", поэтому я думаю, что если "% s" имеет длину n, то вся строка будет иметь значение n * 2 + 1 + 1 + 1 + 1 = 2n + 4, а не 2n + 3... не забывайте заканчивать '\ 0' ,,, но что касается того, должно ли это вызвать ошибку сегментации ... я понятия не имею ...

// Да, много ошибок, касающихсяколичество байтов, выделяемых в этом фрагменте кода ...

...