Мой код пропускает память? - PullRequest
0 голосов
/ 03 июня 2018

У меня есть фрагмент кода, который принимает аргумент командной строки, состоящий из двух чисел, разделенных двоеточием (например, 1: 8), и преобразует его в соответствующие целочисленные значения:

const char delimiter[] = ":";
int numOne = 0, numTwo = 0;
char *tmp = (char *)calloc(16, sizeof(char));

tmp = strtok(argv[i+1], delimiter);
numOne = atoi(tmp);
while (tmp != NULL) {
    numTwo = atoi(tmp);
    tmp = strtok(NULL, argv[i+1]);
}

free(tmp);

Этот код работаетотлично, однако, я узнал, что функция atoi () не имеет никакой реализованной обработки ошибок.Таким образом, если задано слишком большое значение, программа может продолжить работу с неопределенным поведением.

По этой причине я хотел бы заменить его на strtol () и попробовать его так:

const char delimiter[] = ":";
int numOne = 0, numTwo = 0;
char *end;
char *tmp = (char *)calloc(16, sizeof(char));

tmp = strtok(argv[i+1], delimiter);
numOne = strtol(tmp, &end, 10);
if (errno == ERANGE) {
    printf("range error\n");
}
// ...

free(tmp);

Теперь, хотя функция strtol () работает нормально, если преобразованные значения являются действительными целыми числами, я получаю следующую ошибку, если в качестве параметра командной строки передано слишком большое число:

*** Error in `program`: free(): invalid pointer: 0x0000007fefc4077b ***

Может кто-нибудь объяснить мне, пожалуйста, почему free (tmp) не требуется во второй версии кода?А что происходит с изначально выделенной областью памяти?Это течет?Если это так, это проблема, или она может быть просто перераспределена другой программой, как я предполагаю?

1 Ответ

0 голосов
/ 03 июня 2018

strtok ничего не выделяет, strok возвращает указатель на предоставленную строку.free этот указатель приведет к сбою программы.Strtok работает примерно так:

char* my_strtok(char* String, char Delim)
{
  static char* pTerminus;
  static char  TerminateChar;
  if (String==NULL) //continue search and return next token
  {
     if (pTerminus==NULL) return NULL;
     *pTerminus = TerminateChar; //Restore original string 
     String = pTerminus+1;       //Continue search right behind of last token
  }

  pTerminus = strchr(String, Delim); //Find end of token
  if (pTerminus==NULL) return String; //Final token found

  TerminateChar = *pTerminus;  //back-up delimiter
  *pTerminus='\0';             //Terminate found token
  return String;
}

Кроме того, память, предоставленная до вызова calloc, теряется.

...