2015-02-12 2 views
0

Я написал программу, которая анализирует строку в соответствии с этим форматом:strtok() отличаются по составителям

somethingsomething:number: 

На моем компьютере эта программа работает безупречно. Однако, как только я загрузил код и скомпилировал его на компьютер школы, strtok() имеет другое поведение.

Например, с этой строкой: p2test/f4.txt:1:, на моем компьютере первый токен будет p2test/f4.txt. Однако на компьютере школы токен заканчивается p2test/f4.t.

Вот фрагмент кода:

  char *token; 
      char delim[1] = ":"; 

      if ((token = strtok(tmp_string, delim)) != NULL) { 
       ... 
      } 

Здесь tmp_string бы p2test/f4.txt:1:.

Вот версия компилятора моего компьютера: GCC версии 4.9.1 (Ubuntu 4.9.1-16ubuntu6)

Вот версия компилятора моей школы: GCC версии [редакция НКУ-4_8-филиал 202388] 4.8.1 20130909 (SUSE Linux)

+0

Неопределенное поведение отличается accross компьютеры, пожалуйста, разместите остальную часть кода, точно как генерируется 'tmp_string'. –

+4

'char delim [1] =": ";' Это скомпилировано? В этом строковом литерале есть два символа, но вы объявили массив из 1 символа. Другой символ - это нулевой ограничитель. – PaulMcKenzie

+0

@PaulMcKenzie О, вы правы! Это странно, потому что я включил все предупреждения и педанты тоже. – mrQWERTY

ответ

1

Другая проблема заключается в том, что у вас есть память перезаписать здесь:

char delim[1] = ":"; 

Есть два символа в строке, а не 1. Гораздо безопаснее сделать это:

char delim[] = ":"; 
+0

'char delim [1] =": ";' intializes 'delim' для одного символа и не означает, что существует следующий' '\ 0''.Небезопасно использовать 'char delim [] =": ";', it или 'char delim [2] =": ";' то, что ожидает алгоритм. – philipxy

1

Помимо пары вопросов, отмеченных в комментариях, похоже, что с кодом возникает большая проблема. Согласно описанию функции GetLine() в человеке страницы:

If *lineptr is set to NULL and *n is set 0 before the call, then get‐ 
    line() will allocate a buffer for storing the line. This buffer should 
    be freed by the user program even if getline() failed. 

    Alternatively, before calling getline(), *lineptr can contain a pointer 
    to a malloc(3)-allocated buffer *n bytes in size. If the buffer is not 
    large enough to hold the line, getline() resizes it with realloc(3), 
    updating *lineptr and *n as necessary. 

Вы не инициализирует tmp_string, следовательно, его значение некоторые неинициализированным нежелательной, что указывает на некоторый случайный адрес, а вторая альтернатива происходит поведение getline(), описанное выше.

Это выглядит как неопределенное поведение для меня.

P.S. Вы инициализировали значение длины до 0 байтов, которое, согласно man-странице getline(), вызывает вызов realloc. Итак, мне кажется, что ваш код оказывается косвенным, передавая указатель мусора на realloc.

+0

Я действительно заметил это в другой функции, которую я написал при отладке в gdb. Безопаснее ли в будущем устанавливать все неинициализированные указатели на NULL? – mrQWERTY

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