2016-03-12 4 views
0
typedef struct _TRANSITION TRANSITION; 

typedef struct { 
    char name[4]; 
    bool is_initial; 
    bool is_final; 
    TRANSITION *transitions; 
    int number_transitions; 
} STATE; 

struct _TRANSITION { 
    char c; 
    STATE *dest; 
}; 

void destroy_state(STATE **pp_state) { 
     if (pp_state != NULL && *pp_state != NULL) { 
      free((*pp_state)->transitions); 
      (*pp_state)->transitions = NULL; 
     } 
     free(*pp_state); 
     *pp_state = NULL; 
    } 

Что я хочу сделать, это удалить STATE. Поэтому мне нужно освободить все мое состояние TRANSITION. Здесь вы можете увидеть функции, которые создают эти структуры:Освобождение памяти от массива структурных переменных

STATE *create_state(char *name, bool is_initial, bool is_final) { 
    STATE *state = (STATE *) malloc(sizeof(STATE)); 
    if (state != NULL) { 
     strcpy(state->name, name); 
     state->is_initial = is_initial; 
     state->is_final = is_final; 
     state->transitions = NULL; 
     state->number_transitions = 0; 
    } 
    return state; 
} 

void add_transition(STATE *source, char sign, STATE *dest) { 
    if (source != NULL && dest != NULL) { 
     TRANSITION *transitions = source->transitions; 
     TRANSITION *trans = source->transitions; 
     int i; 
     if (transitions != NULL) { 
      transitions = (TRANSITION *) realloc(transitions, sizeof(TRANSITION) * ((source->number_transitions) + 1));   
     } else { 
      transitions = (TRANSITION *) malloc(sizeof(TRANSITION)); 
     } 
     trans = (transitions + source->number_transitions); 
     trans->c = sign; 
     trans->dest = dest; 
     (source->number_transitions)++; 
     source->transitions = transitions; 
    } 
} 

Однако, как я проверил свою функцию в главном методе с этим:

STATE *first = create_state("S'0", true, false); 
STATE *second = create_state("S'1", false, false); 
printf("%s: Initial: %d, Final: %d\n", first->name, first->is_initial, first->is_final); 
add_transition(first, 'A', second); 
add_transition(first, 'B', second); 
add_transition(first, 'C', second); 
TRANSITION *transition = first->transitions; 
printf("%c", transition[0].c); // Output: A 
printf("%c", transition[1].c); // Output: B 
printf("%c\n", transition[2].c); // Output: C 

destroy_state(&first); 

printf("%c", transition[0].c); // Output: 
printf("%c", transition[1].c); // Output: B 
printf("%c", transition[2].c); // Output: C 

Похоже, что я просто удален первым TRANSITION (Результат прокомментировал функции printf()).

Очевидно, что я сделал что-то неправильно. Мое первое решение этой проблемы состояло в том, что я должен перебирать переходы. Но так как я просто выделяю пространство для одного массива TRANSITION, я не вижу, что это работает (и, как я и ожидал, это не сработало).

В чем моя ошибка?

+3

Не связанные с вашей проблемой, но имена символов, начинающиеся с символа подчеркивания, за которым следует заглавная буква, зарезервированы для «реализации» (т. Е. Для компилятора и стандартной библиотеки). –

+0

И имена всех прописных букв должны использоваться только для enum-констант и макросов. – Olaf

ответ

0

Когда вы

TRANSITION *transition = first->transitions; 

вы сохранить указатель на память. Затем вы освобождаете память, но это не меняет указатель transition, который вы определили и инициализировали выше. Итак, когда вы разыскиваете transition, вы получаете доступ к памяти, которая не выделена, и у вас есть undefined поведение.

Вы должны помнить, что так же, как выделение памяти не инициализирует содержимое выделенной памяти, освобождение памяти ничего не делает для содержимого памяти. Поэтому, когда вы получаете доступ к нему после его освобождения, его части могут сохранять прежнее содержание.

+0

Но я не установил его в 'NULL' в функции' destroy_state'? Разве это не значит, что мы должны установить переменную 'NULL', чтобы поведение не было точным? – Goldi

+1

@DennisvonEich Нет, вы устанавливаете 'first-> transitionitions' в' NULL', любая другая переменная является отдельной. Например, если у вас есть, например, 'int a = 5, b; b = a; a = 0; 'вы не ожидали, что переменная' b' изменится, когда вы измените переменную 'a'? Здесь то же самое, вы изменяете одну переменную и не имеете никакого отношения к каким-либо другим переменным, просто случается, что у вас есть две разные переменные с одинаковым значением. –

+0

Я вижу. Поэтому я могу исправить эту проблему, просто установив переменную, подобную этой «transition = first-> transitionitions», и снова обновится. Правильно? Я имею в виду, прежде чем снова получить доступ к нему после вызова метода, который освобождает память. – Goldi

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