2016-01-13 3 views
4

Не могли бы вы помочь мне? Мой код делает tokenizing, так что я создал такой код:Освобождение памяти после вызова strtok() вызывает ошибку

  1. я выделить память,
  2. Я strcpy(malloced_memory, argv)
  3. исполняю strtok(mallocted_memory, ".")
  4. free(mallocted_memory) Попробуйте.

    filename = malloc(strlen(argv)); 
    
    strcpy(filename, argv); 
    strk_ptr = malloc(sizeof(filename)); 
    strk_ptr = strtok(filename,".");// 
    i++; 
    sprintf(in->file_name,"%s",strk_ptr); 
    
    while(strk_ptr = strtok(NULL,"."))// 
    { 
        i++; 
        sprintf(in->file_name,"%s.%s",in->file_name,strk_ptr); 
        sprintf(in->file_ext ,"%s",strk_ptr); 
    } 
    free(strk_ptr); 
    free(filename); 
    

Этот код имеет проблему, я не могу free(filename). Если я попробую free(filename), тогда программа получит SIGTRAP. Но программа работает.

Я хочу исправить эту проблему. Что мне делать?

ответ

1
filename = malloc(strlen(argv)); 
strk_ptr = malloc(sizeof(filename)); 

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

Так что не malloc strk_ptr. Просто оставьте его в символьном *, то только свободное имя файла в конце

3

Эта линия:

filename = malloc(sizeof(argv)); 

должен быть таким:

filename = malloc(strlen(argv) + 1);  /* +1 for the '\0' at the end */ 
if (filename == NULL) { /* take some action */ } 

И эта линия:

strk_ptr = malloc(sizeof(filename)); 

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

strk_ptr = strtok(filename,"."); 

И вы должны проверить возвращаемое значение:

strk_ptr = strtok(filename,"."); 
if (strk_ptr == NULL) { /* take some action */ } 

BTW, функция strtok() возвращает указатель на маркер внутри строки, переданной в первоначальном вызове к нему (filename в вашем примере). Он не выделяет память, поэтому его возвращаемое значение НЕ должно быть освобождено (которое ваша программа избегает, но это распространенная ошибка). В то время как я заучиваю около strtok(), я упомянул, что вы не можете (прямо или косвенно) передать ему буквенную строку для tokenize, так как она изменяет строку, а буквальные строки - только для чтения. То есть, делает: strtok("sample.txt", ".") - это не-go.

И, наконец, этот вид косвенного условия не большая форма:

while (strk_ptr = strtok(NULL,".")) { ... } 

Лучше:

while ((strk_ptr = strtok(NULL,".")) != NULL) { ... } 
+0

они не просят об освобождении strtok памяти, они просят об освобождении их памяти после использования strtok. –

+0

@KeithNicholas Спасибо, немного рассказать –

0
strk_ptr = malloc(sizeof(filename)); 
strk_ptr = strtok(filename,".");// 
... 
free(strk_ptr); 

не работает. Сначала strk_ptr указывает на память malloc'd, но затем указатель немедленно перезаписывается каким-либо другим значением, поэтому в основном вы теряете указатель на память malloc'd и, следовательно, не можете больше free.

Edit:

malloc(sizeof(filename)) Видя, я должен добавить, что вы не должны выделять память для самой переменной указателя. Объявление char* strk_ptr; заставляет компилятор неявно выделять память для этого указателя (т. Е. 4 или 8 байтов). Таким образом, вы можете просто использовать указатель напрямую, как и любую другую переменную, и вам не понадобится free память этой переменной.

char* strk_ptr; 
strk_ptr = strtok(filename,"."); 

Или, если это не ваше намерение, то обратите внимание, что sizeof(filename) делает не возвращают длину строки, но только размер переменной указателя filename, то есть, как правило, 4 или 8, независимо от каких строка filename указывает на. Смотрите также http://www.gnu.org/software/libc/manual/html_node/String-Length.html:

char string[32] = "hello, world"; 
char *ptr = string; 
sizeof (string) 
    ⇒ 32 
sizeof (ptr) 
    ⇒ 4 /* (on a machine with 4 byte pointers) */ 
+0

@JohnHascall Да, вы правы. – JimmyB

2

Вам не нужно выделять память при использовании strtok()

Там нет никаких проблем в освобождении файла как правильно выделено таНос() , однако есть много других проблем и утечек памяти. В основном вы первый выделить память для str_ptr:

strk_ptr = malloc(sizeof(filename)); 

Здесь таНос() возвращает указатель, который хранится в strk_ptr. А потом вы звоните strtok() который также возвращает указатель внутри файла:

strk_ptr = strtok(filename,"."); 

Таким образом, вы потеряли первоначальный указатель, возвращаемый таНос() и теперь strk_ptr точки где-то в имя файла. Когда вы вызываете free(str_ptr), вы освобождаете память внутри filename. Последующий вызов free(filename) сообщает об ошибке. Решение простое, что не нужно выделять память для strk_ptr.

Я написал рабочий минимальный код, чтобы показать вам, как правильно использовать strtok. Пожалуйста, помните, что, задавая вопрос, размещение минимального рабочего кода всегда лучше.

int main(int argc, char **argv) { 

    char *strk_ptr; 
    char *filename = malloc(strlen(argv[0]) + 1); 

    strcpy(filename, argv[0]); 

    printf("filename = %s, size = %zu\n", filename, sizeof(filename)); 

    // Do not malloc this 
    //strk_ptr = malloc(strlen(filename) + 1); 
    strk_ptr = strtok(filename,".");// 
    printf("%s\n", strk_ptr); 

    while((strk_ptr = strtok(NULL,"."))) 
    { 
     printf("%s\n", strk_ptr); 
    } 
    free(filename); 

    return 0; 
} 

Прежде всего ARGV это символ **, так что если вы хотите, чтобы скопировать содержимое первого аргумента, переданного в качестве входных данных вы должны использовать ARGV [0], который всегда исполняемый файл имя.

then, sizeof(filename) возвращает размер указателя не тот контент, как filename не является массивом. вы должны использовать strlen(filename) + 1.

strtok возвращает указатель внутри объекта (имя файла), которое уже выделено, так что вы не нужно выделить память для strk_ptr.

При использовании strtok в цикле рассмотрят принять следующий подход:

for (strk_ptr = strtok(filename, "."); strk_ptr; strk_ptr = strtok(NULL, ".")) 
    { 
     printf("%s\n", strk_ptr); 
    }