Почему структуры локальных переменных не сбрасываются при выходе из области видимости? - PullRequest
0 голосов
/ 15 марта 2012

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

...

else if(pstrcmp(input, (char*)"check", 5)){
            int checkIndex = getIndex(input[6], input[7] - 49);
            printf("checkindex %i\n", checkIndex);
            if(!(checkIndex < 0 || checkIndex > 127)){
                //we've received a valid check
                struct m mUn[MOVE_BUFF];
                gen_psm(checkIndex, mUn);
                int i = 0;
                while(mUn[i].start != mUn[i].end && i < MOVE_BUFF){
                    printf("%s\n", GSQ(mUn[i].end));
                    i++;
                }
            }
        }

...

Первая строка - это просто проверка ввода.Основная часть кода находится между struct m mUn[MOVE_BUFF] и циклом while.Поэтому я создаю массив struct m, который я создал, и он содержит несколько целочисленных значений, определяющих конкретный ход, а затем я передаю его в gen_psm, который принимает индекс квадрата для проверки и массив для заполнения.Он заполняет массив действительными ходами для фигуры, расположенной в индексе.Прекрасно и модно для первого хода.Затем я пытаюсь сделать второй шаг и обнаруживаю, что в массиве все еще содержатся данные с первого шага, хотя я уже давно вышел из области действия mUn, в котором я его объявил.Это какой-то характер структур, что он сохраняет свои данные?Нужно ли мне заполнять 0 целиком (когда я пробовал его, мне показалось, что он заполнен нулями).Если мне нужно заполнить 0, есть ли более быстрый способ (если мне нужно заполнить 0 несколько раз 100 миллионов раз, это проблема)?

Ответы [ 5 ]

7 голосов
/ 15 марта 2012

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

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

2 голосов
/ 15 марта 2012

Попробуйте

struct m mUn[MOVE_BUFF] = {0};

(Вы можете выбрать более подходящее имя для своей структуры, чем просто 'm')

1 голос
/ 15 марта 2012

У вас нет гарантии, что компилятор будет делать с памятью, которую вы не используете.Как правило, это просто оставляет его в покое.Если вы хотите, чтобы ваша память была инициализирована, вы должны инициализировать ее.Большие секции памяти могут быть эффективно установлены на ноль с помощью memset (), но убедитесь, что вы не касаетесь памяти, которой вы не владеете.

1 голос
/ 15 марта 2012

Нет гарантии, что данные будут очищены, и для целей производительности они не очищаются при выходе из области действия, это просто неопределенное поведение для чтения или изменения.

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

0 голосов
/ 15 марта 2012

Реальный ответ: "с чего бы он сам себя сбросил?"Если вы не инициализировали память, она по определению находится в неопределенном состоянии.(Тот факт, что это могут быть шестнадцатеричные нули при первом проходе, совсем не является чем-то, на что вы можете положиться.)

Вы обязательно должны сбросить его.

Что касаетсясамый быстрый способ сделать это, ну ...

memset будет моей первой попыткой.Если бы это было на самом деле слишком медленно, я бы, вероятно, создал фиктивную структуру того же размера, заполнил бы THAT пустыми значениями и сделал бы memcpy из нее поверх локальной.Это безобразно, но я не ожидаю, что вы получите что-то быстрее, чем это.

...