2012-03-25 2 views
0

Я создаю создателя make-файла, но я застрял в этой ошибке на sprintf. Самое интересное, что у меня есть несколько 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); 
    } 
} 
+0

Мое лучшее предположение заключается в том, что одна из строк не является нулевой. У меня была эта проблема пару раз, когда я впервые учился C. – forivall

ответ

1

Это не похож, как вы направляете 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

Извините, что код, который я опубликовал, был старым, а распределение TEMP было исправлено, но ошибка сегментации не исходит от TEMP, а из sprintf (f.name .....). Это то, что я нашел странным, даже с f.name = malloc (sizeof (char) * (strlen (direntp-> d_name) * 2 + 3 + 1)) все равно запускает ту же ошибку. –

0

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

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

0

Вы не выделяли enougth памяти для этого Sprintf:

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

Спасибо, но, как я уже сказал в других комментариях, это была не ошибка, хотя теперь TEMP имеет коррекцию seg fault is from sprintf (f.name .....) –

+0

sprintf (f.name, "% s /% sa ", direntp-> d_name, direntp-> d_name, я вижу 2 * strlen (direntp-> d_name) + 3 char + 1 дополнительный символ (\ 0 для конца строки). Вы выделили 2 * strlen (direntp -> d_name) + только 3 символа. Вы пропустили область \ 0 вашей строки. Редактирование arf не видел, что вы пытались это раньше. – grifos

0

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

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

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

  3. Задача, которую вы выполняете, намного лучше подходит для некоторых языков сценариев (Perl, Python, Tcl, Ruby, что угодно), если только некоторые внешние странные обстоятельства не заставляют вас использовать C; C допускается в Unix-способе, чтобы выполнять области, более близкие к ядру и низкому уровню. См. "The Art of Unix Programming" для рассуждения.

+0

Это проект из моего университета, поэтому я должен использовать C, я знаю asprintf () лучше, но у меня есть некоторые ограничения, какие команды я могу использовать. –

Смежные вопросы