Отладка Xcode C изменяет значения указателей при пошаговом выполнении


Я отлаживаю C-код, в котором у меня есть указатель внутри указателя на структуру с именем board. Есть функция, где я печатаю плату:

static void board_print(board *b){
    int i,j;
    char data;
    for (i = 0; i < size; i++) {
        for (j = 0; j < size; j++) {
            data = b->data[i * size + j];
            if(data){
                printf("X ");
            }else{
                printf("O ");
            }
        }
        printf("n");
    }
}

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

первый

Затем я вхожу в цикл в первый раз, когда i и j равны нулю, и b->data[0] должно быть совершенно верно, так как оно было два шага назад. Внезапно, как только я перехожу на строку data = b->data[i * size + j];, указатель данных превращается в нулевой указатель. Когда я выполняю строку, я (очевидно) получаю плохую ошибку доступа, как показано ниже:

второй

В чем может быть причина? Я уже использовал C раньше, и я довольно хорошо его понимаю, но я никогда не видел, чтобы значение указателя внезапно менялось на null, когда вы входите в однопоточную простую программу C. Я использую Apple LLVM Compiler 4.1 для компиляции и lldb для отладки, которые это значения по умолчанию для XCode 4.5.

Update : такое же поведение наблюдается при компиляции с gcc и отладке с gdb. Почти стопроцентный аррор на моей стороне, но я понятия не имею, что не так с кодом..

Обновление #2: я заметил кое-что еще более странное на gcc/gdb сейчас. Непосредственно перед выполнением строки data = b->data[i * size + j];, я могу получить доступ ко всему из отладчика без проблем. Сразу после выполнения этой строки я не могу получить доступ к b->data полностью, включая значения, к которым я обратился непосредственно перед шагом:

третий

После строки $4 = ..., успешно выполненной в отладчике, я перешагнул через нее. Затем у меня есть различные ошибки адресации, как показано выше. Я действительно понятия не имею, что происходит...

Обновление #3: я заметил кое-что очень странное. Вот, сначала посмотрите на исправление, которое я реализовал. Этот начал работать без проблем, когда я избавился от переменной с именем data полностью:

четвёртый

Теперь внимательно посмотрите на скриншот, который я загрузил с обновлением #2: Сразу после того, как я присвоил значение локальной переменной с именем data, также b->data получает свой адрес изменен. Это выглядит как побочный эффект задания. Но я понятия не имею, что за этим кроется.
1 3

1 ответ:

Очевидно, что что-то / кто-то изменяет свойство "данные" структуры платы.

Почему ? Я вижу только 3 причины:

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

  • Структура платы выделяется из стека, но содержание больше не является действительным... Например: возвращается указатель на локальную переменную, но переменная (структура) уничтожается (поскольку это локальная переменная) при возврате указателя...

  • Структура платы выделяется из кучи, затем освобождается, и, наконец, этот освобожденный указатель все еще используется : память кучи повреждена чем-то другим...

Мое предположение: второй пункт, который является частой ошибкой

Итак, простой вопрос : структура платы хранится в памяти кучи или стека ?