0

Я знаю, что этот вопрос существует и в других местах, как:Указатель освобождения не был выделен массив строк в C

pointer being freed was not allocated in C error: pointer being freed was not allocated

, но я все еще очень смущен. Ошибки, по-видимому, связаны с такими вещами, как «изменение исходного указателя, возвращаемого malloc» и «отказ от malloc до освобождения». Я просто не понимаю, как эти причины относятся к моей программе.

Я пишу динамически выделенный массив строк:

#include <stdio.h> 
#include <stdlib.h> 

#define NLETTERS 25 

typedef struct { 
    char** array; 
    size_t used; 
    size_t size; 
} array_t; 

array_t* initArray(size_t initialSize) { 
    array_t* a = malloc(sizeof(array_t)); 
    a->array = malloc(initialSize*sizeof(char*)); 
    a->used = 0; 
    a->size = initialSize; 

    int i; 
    for(i = 0; i < initialSize; i++) { 
     a->array[i] = malloc(sizeof(char) * NLETTERS); 
    } 

    return a; 
} 

void insertArray(array_t *a, char* element) { 
    if (a->used == a->size) { 
     a->size *= 2; 

     a->array = realloc(a->array, a->size * sizeof(char*)); 

     int i; 
     for(i = (int)a->used; i < a->size; i++) { 
      a->array[i] = malloc(sizeof(char) * NLETTERS); 
     } 
    } 
    a->array[a->used++] = element; 
} 

void freeArray(array_t *a) { 
    int i; 
    for(i = 0; i < a->size; i++) { 
     free(a->array[i]); 
    } 

    free(a->array); 
    free(a); 
    a->array = NULL; 
    a->used = a->size = 0; 
} 

void print_array(array_t *a) { 
    int i; 
    for(i = 0; i < a->size; i++) { 
     printf("%s\n", a->array[i]); 
    } 
} 

int main(int argc, const char * argv[]) { 
    array_t *a; 
    a = initArray(2); 
    insertArray(a, "hello"); 
    insertArray(a, "how are you"); 
    print_array(a); 
    insertArray(a, "yup"); 
    insertArray(a, "you know it"); 
    print_array(a); 

    freeArray(a); 

    return 0; 
} 

При попытке «бесплатно», я получаю ошибку: «указатель освобождения не было выделено» право на

free(a->array[0]) 

в первой итерации цикла for в freeArray();

Справка была бы принята с благодарностью.

+0

Вы полагаете, что мой перераспределить неверна? С чем это должно измениться? Я не совсем понимаю, какое исправление находится под этой ссылкой. – Chris

+0

Обратите внимание, что в 'insertArray()' у вас есть idiom 'old_ptr = realloc (old_ptr, new_size);'. Это плохо. Если (когда!) 'Realloc()' fail, вы пропустите память, потому что 'old_ptr' переписан с помощью NULL, поэтому вы больше не можете освобождать старую память, даже если она все еще выделена. Используйте 'new_ptr = realloc (old_ptr, new_size); if (new_ptr == NULL) {... сообщить об ошибке и т. д.} old_ptr = new_ptr; '(и обычно также' old_size = new_size; 'тоже). –

ответ

2

В своем коде, говоря

a->array[a->used++] = element; 

вы перезапись выделенной памяти malloc(), поэтому, позже при прохождении его free() вызывает вопрос.

Связанные со ссылкой на C11, глава §7.22.3.3, free функция, (курсив мой )

The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

Кроме того, на более позднем этапе, это вызывает memory leak, как память, выделенную malloc() не получает free() -d, фактически.

Решения: Вы должны использовать strcpy() для копии содержания в выделенной памяти.

0

Источником проблемы является строка:

a->array[a->used++] = element; 

Он имеет две проблемы:

  1. Это утечка памяти. Память, возвращаемая malloc(), теряется.

  2. Он указывает только на память, используемую для строковых литералов, что вызывает проблемы при вызове free.

Замените эту строку с

strcpy(a->array[a->used++], element); 
0

Я вижу две проблемы: -

  1. a->array[a->used++] = element;
    Вы выделили память, но Inplace использования, что вы снова связав его в другом месте, что приводит к утечке памяти. Поэтому измените его на: -

    strcpy (a-> array [a-> used ++], element);

  2. Изменить FreeArray как это (вы освобождаете память и используете ее, что приводит к ошибке seg).

    void freeArray(array_t *a) { 
        int i; 
        for(i = 0; i < a->size; i++) { 
         free(a->array[i]); 
        } 
    
        free(a->array); 
        a->array = NULL; 
        a->used = a->size = 0; 
        free(a); 
    } 
    

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

  • Нет связанных вопросов^_^