Как закончить с указателем на 0xCCCCCCCC - PullRequest
6 голосов
/ 01 сентября 2010

Программа, с которой я работаю при сбоях, иногда пытается прочитать данные по адресу 0xCCCCCCCC. Google (и StackOverflow) - мои друзья. Я увидел, что это код отладки MSVC для неинициализированной переменной стека. Чтобы понять, откуда может возникнуть проблема, я попытался воспроизвести это поведение: проблема в том, что я не смог этого сделать.

Вопрос: есть ли у вас фрагмент кода, показывающий, как указатель может заканчиваться указанием на 0xCCCCCCCC?

Спасибо.

Ответы [ 4 ]

10 голосов
/ 01 сентября 2010
int main()
{
    int* p;
}

Если вы создаете с помощью среды отладки Visual C ++, ставите точку останова в main() и запускаете, вы увидите, что p имеет значение 0xcccccccc.

6 голосов
/ 01 сентября 2010

Скомпилируйте ваш код с помощью переключателя компилятора / GZ или / RTCs . Убедитесь, что / Od switch также используется для отключения любых оптимизаций.

S

Включает проверку ошибок времени выполнения стека следующим образом:

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

  • Обнаружение переполнения и переполнения локальных переменных, таких как массивы. / RTC не будут обнаруживать переполнения при доступе к памяти, которая является результатом заполнения компилятором внутри структуры. Заполнение может происходить с использованием align (C ++), / Zp (Struct Member Alignment) или pack, или если вы упорядочиваете элементы структуры таким образом, чтобы компилятору требовалось добавить заполнение.

  • Проверка указателя стека, который обнаруживает повреждение указателя стека. Повреждение указателя стека может быть вызвано несоответствием соглашения о вызовах. Например, используя указатель на функцию, вы вызываете функцию в DLL, которая экспортируется как __stdcall, но вы объявляете указатель на функцию как __cdecl.

2 голосов
/ 01 сентября 2010

У меня нет MSVC, но этот код должен создавать проблему и компилироваться без предупреждений.

В файле f1.c:

void ignore(int **p) { }

В файле f2.c:

void ignore(int **p);
int main(int c, char **v)
{
  int *a;
  ignore(&a);
  return *a;
}

При вызове ignore создается впечатление, что a может быть инициализирован. Я сомневаюсь, что компилятор предупредит в этом случае из-за риска того, что предупреждение может быть ложным срабатыванием.

0 голосов
/ 01 сентября 2010

Как насчет этого? Игнорируйте предупреждение, которое VC бросает во время работы.

struct A{
    int *p;
};

int main(){
    A a;
    cout << (void *)a.p;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...