[vs2010] инициализация памяти под дебугером
От: uzhas Ниоткуда  
Дата: 03.08.11 18:08
Оценка:
сегодня столкнулся с интересной проблемой: юнит-тест фейлится в релизе, но когда запускаешь тот же ехе-шник под студией, то ничего не фейлится
пораскинув мозгами , определил, что сырые массивы инициализируются по-разному
struct A
{
  char Value[10];
};
A a; <- вот тут имеем неинициализированные данные в одном случае и нулевые в другом случае


про работу с неинициализированными данными мы в курсе и вопрос в другом:
как VS2010 дебугер влияет на инициализацию массивов простых типов? что-то подменяется (аллокаторы, рантайм, спец. страницы памяти, особенность адреса подгрузки)? разъяснения\ссылочки приветствуются
зы: отмечу, что описанные поведения стабильные. то бишь постоянно тест фейлится без дебугера и всегда проходит успешно в дебугере
зы2: из студии делал _запуск_ приложения. аттач к уже запущенному не делал (паузу вставлять в тест надо, лениво)
Re: [vs2010] инициализация памяти под дебугером
От: ononim  
Дата: 03.08.11 18:15
Оценка:
U>зы: отмечу, что описанные поведения стабильные. то бишь постоянно тест фейлится без дебугера и всегда проходит успешно в дебугере
U>зы2: из студии делал _запуск_ приложения. аттач к уже запущенному не делал (паузу вставлять в тест надо, лениво)
Под дебагом включаются разные дебажные фичи хипа. Изза чего он кстати работает гораздо медленнее.
Как много веселых ребят, и все делают велосипед...
Re: [vs2010] инициализация памяти под дебугером
От: const_volatile  
Дата: 03.08.11 18:38
Оценка:
Здравствуйте, uzhas, Вы писали:

U>как VS2010 дебугер влияет на инициализацию массивов простых типов? что-то подменяется (аллокаторы, рантайм, спец. страницы памяти, особенность адреса подгрузки)? разъяснения\ссылочки приветствуются


эта информация размазана тонким слоем по всему msdn, так что внятную ссылку удалось найти только на стэковерфло.

http://stackoverflow.com/questions/5368587/an-error-only-occurs-in-release-mode

  • debug initializes dynamically allocated variables by a bad value (this is done by debug runtime library, controlled by Code generation/Runtime library)
  • debug initializes stack allocated variables by a bad value (controlled by Code generation/Basic runtime checks — /RTC options)
  • optimizations are turned off in debug (controlled by Optimization — /O options)
  • different macros are defined (_DEBUG vs NDEBUG) (controlled by Preprocessor/Preprocessor defintions)
  • Re[2]: [vs2010] инициализация памяти под дебугером
    От: uzhas Ниоткуда  
    Дата: 03.08.11 19:40
    Оценка:
    Здравствуйте, const_volatile, Вы писали:

    _>эта информация размазана тонким слоем по всему msdn, так что внятную ссылку удалось найти только на стэковерфло.

    не увидел полезную инфу там

    акцентирую внимание на ранее описанном:

    дебужная сборка работает одинаково хорошо в студии и вне её
    Re: [vs2010] инициализация памяти под дебугером
    От: netch80 Украина http://netch80.dreamwidth.org/
    Дата: 03.08.11 21:27
    Оценка:
    Здравствуйте, uzhas, Вы писали:

    U>сегодня столкнулся с интересной проблемой: юнит-тест фейлится в релизе, но когда запускаешь тот же ехе-шник под студией, то ничего не фейлится

    U>пораскинув мозгами , определил, что сырые массивы инициализируются по-разному
    U>
    U>struct A
    U>{
    U>  char Value[10];
    U>};
    U>A a; <- вот тут имеем неинициализированные данные в одном случае и нулевые в другом случае
    U>


    U>про работу с неинициализированными данными мы в курсе и вопрос в другом:

    U>как VS2010 дебугер влияет на инициализацию массивов простых типов? что-то подменяется (аллокаторы, рантайм, спец. страницы памяти, особенность адреса подгрузки)? разъяснения\ссылочки приветствуются

    Может, просто malloc выдаёт всегда очищенную память? (Предположение навскидку)

    Жаль, если это не настраивается. Хороший пример настраиваемости традиционно даёт FreeBSD'шный malloc. По умолчанию память не чистится, но есть флаг заливать нулевыми байтами при выдаче, а есть флаг заливать 0xa5 при выдаче и 0x5a при возврате. Регулируя ими режим работы, можно заваливать программу и по этому определять ошибки
    The God is real, unless declared integer.
    Re: [vs2010] инициализация памяти под дебугером
    От: _nn_ www.nemerleweb.com
    Дата: 04.08.11 15:11
    Оценка:
    Здравствуйте, uzhas, Вы писали:

    U>сегодня столкнулся с интересной проблемой: юнит-тест фейлится в релизе, но когда запускаешь тот же ехе-шник под студией, то ничего не фейлится

    U>пораскинув мозгами , определил, что сырые массивы инициализируются по-разному
    U>
    U>struct A
    U>{
    U>  char Value[10];
    U>};
    U>A a; <- вот тут имеем неинициализированные данные в одном случае и нулевые в другом случае
    U>


    Не совсемя ясно что вы хотите чтобы было.
    Если вы не указываете как ининциализировать, то может быть там все что угодно.
    Пишите
    A a = {0};

    И не будет проблем.

    Или конструктор предоставьте с затиранием нулями.
    http://rsdn.nemerleweb.com
    http://nemerleweb.com
    Re[2]: [vs2010] инициализация памяти под дебугером
    От: uzhas Ниоткуда  
    Дата: 04.08.11 15:46
    Оценка:
    Здравствуйте, _nn_, Вы писали:

    __>Не совсемя ясно что вы хотите чтобы было.

    я хочу узнать, как дебугер влияет на выполнение уже собранного бинаря, потому что фиксить баги, которые не воспроизводятся под дебугером и воспроизводятся без дебугера очень сложно
    Re[3]: [vs2010] инициализация памяти под дебугером
    От: _nn_ www.nemerleweb.com
    Дата: 04.08.11 15:55
    Оценка:
    Здравствуйте, uzhas, Вы писали:

    U>Здравствуйте, _nn_, Вы писали:


    __>>Не совсемя ясно что вы хотите чтобы было.

    U>я хочу узнать, как дебугер влияет на выполнение уже собранного бинаря, потому что фиксить баги, которые не воспроизводятся под дебугером и воспроизводятся без дебугера очень сложно

    Тут также может влиять билд Debug или Release , а не только запуск с отладчиком или без.

    Вообще, VC выдает предупреждение если используется неинициализированная переменная .
    Поставьте в дебаг сборке флаг /RTCsu, сразу найдете где нет инициализации.

    А гадать что делает компилятор и как инициализируется не вижу смысла.
    Это будет еще один скрытый баг, который выскочит в самый неподходящий момент.
    http://rsdn.nemerleweb.com
    http://nemerleweb.com
    Re: [vs2010] инициализация памяти под дебугером
    От: Mr.Delphist  
    Дата: 04.08.11 20:36
    Оценка:
    Здравствуйте, uzhas, Вы писали:

    U>про работу с неинициализированными данными мы в курсе и вопрос в другом:

    U>как VS2010 дебугер влияет на инициализацию массивов простых типов? что-то подменяется (аллокаторы, рантайм, спец. страницы памяти, особенность адреса подгрузки)? разъяснения\ссылочки приветствуются

    Самый главный ИМХО вопрос так никто и не спросил: а КАК именно фейлится юнит-тест? Падает на AV? Осетра бросает? Исключение? etc

    Вообще, аллокация и инициализация памяти в дебажной сборке штука особая. Про автозабивку памяти магическими константами CD/DD/FE и прочее тут уже упоминали (один код — для неинициализированной памяти, другой — для освобожденной и т.п.). В дополнение: каждая область памяти окружается гвардами из нулей. Поэтому использование, например, строковых функций может чудесно работать на дебаге (опа, нулевой байт, конец строчки!), но в релизе будут происходить чудеса, т.к. скан твоей строчки будет продолжен за её пределами

    Кстати, вот нагуглилось на фразу "debug zero guards":
    http://www.nobugs.org/developer/win32/debug_crt_heap.html
    Re[2]: [vs2010] инициализация памяти под дебугером
    От: ononim  
    Дата: 04.08.11 22:42
    Оценка: 4 (1)
    Здравствуйте, Mr.Delphist, Вы писали:

    MD>Здравствуйте, uzhas, Вы писали:


    U>>про работу с неинициализированными данными мы в курсе и вопрос в другом:

    U>>как VS2010 дебугер влияет на инициализацию массивов простых типов? что-то подменяется (аллокаторы, рантайм, спец. страницы памяти, особенность адреса подгрузки)? разъяснения\ссылочки приветствуются

    MD>Самый главный ИМХО вопрос так никто и не спросил: а КАК именно фейлится юнит-тест? Падает на AV? Осетра бросает? Исключение? etc


    MD>Вообще, аллокация и инициализация памяти в дебажной сборке штука особая. Про автозабивку памяти магическими константами CD/DD/FE и прочее тут уже упоминали (один код — для неинициализированной памяти, другой — для освобожденной и т.п.). В дополнение: каждая область памяти окружается гвардами из нулей. Поэтому использование, например, строковых функций может чудесно работать на дебаге (опа, нулевой байт, конец строчки!), но в релизе будут происходить чудеса, т.к. скан твоей строчки будет продолжен за её пределами

    Дело не тока в дебажности сборки. Если запускать прогу под дебаггером, винда все создаваемые этой прогой хипы — создает дебагнутыми.
    Вот код инициализатора процесса, который это делает:
                    if (Peb->BeingDebugged) {
                        Peb->NtGlobalFlag |= FLG_HEAP_ENABLE_FREE_CHECK |
                                             FLG_HEAP_ENABLE_TAIL_CHECK |
                                             FLG_HEAP_VALIDATE_PARAMETERS;
                        }


    вот фрагмент RtlCreateHeap'а
    
        if (NtGlobalFlag & FLG_HEAP_ENABLE_TAIL_CHECK) {
    
            Flags |= HEAP_TAIL_CHECKING_ENABLED;
        }
    
        if (NtGlobalFlag & FLG_HEAP_ENABLE_FREE_CHECK) {
    
            Flags |= HEAP_FREE_CHECKING_ENABLED;
        }
    
    ...
        if (NtGlobalFlag & FLG_HEAP_VALIDATE_PARAMETERS) {
    
            Flags |= HEAP_VALIDATE_PARAMETERS_ENABLED;
        }


    далее, изза наличия одного из этих флагов, (которые сами по себе гуглябельные):
    PVOID
    RtlAllocateHeapSlowly (
        IN PVOID HeapHandle,
        IN ULONG Flags,
        IN SIZE_T Size
        )
    
    /*++
    
    Routine Description:
    
        This routine does the equivalent of Rtl Allocate Heap but it does it will
        additional heap consistency checking logic and tagging.
    ........
    --*/
    ...................................
                    } else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED) {
    
                        RtlFillMemoryUlong( (PCHAR)(BusyBlock + 1), Size & ~0x3, ALLOC_HEAP_FILL );
                    }


    чтобы этого не было — достаточно поставить переменную окружения _NO_DEBUG_HEAP=1
    но проблему по-любому надо фиксить, потому что отключение дебажных фич лишь уменьшает вероятность воспроизведения, поскольку дебажный хип ВСЕГДА инициализирует выделенную память мусором, а не дебажный — когда захочет.
    Как много веселых ребят, и все делают велосипед...
    Re[3]: [vs2010] инициализация памяти под дебугером
    От: uzhas Ниоткуда  
    Дата: 09.08.11 14:01
    Оценка:
    Здравствуйте, ononim, Вы писали:

    O>Если запускать прогу под дебаггером, винда все создаваемые этой прогой хипы — создает дебагнутыми.

    мне несколько перечитываний понадобилось с интервалом в пару дней, чтобы осознать, что именно эту инфу мне и надо ;=)
    откуда фрагменты кода? где почитать можно? в DDK ? а влинкован это код в какой бинарь? msvcrt100.dll ?
    Re[4]: [vs2010] инициализация памяти под дебугером
    От: ononim  
    Дата: 09.08.11 17:43
    Оценка:
    O>>Если запускать прогу под дебаггером, винда все создаваемые этой прогой хипы — создает дебагнутыми.
    U>мне несколько перечитываний понадобилось с интервалом в пару дней, чтобы осознать, что именно эту инфу мне и надо ;=)
    U>откуда фрагменты кода? где почитать можно? в DDK ?
    кхе. Баян 7етний же: http://www.techspot.com/news/11003-win2k-amp-nt-4-source-code-leaked.html

    U>а влинкован это код в какой бинарь? msvcrt100.dll ?

    ntdll.dll
    Как много веселых ребят, и все делают велосипед...
    Re: [vs2010] инициализация памяти под дебугером
    От: HolyNick  
    Дата: 10.08.11 13:38
    Оценка:
    Попробуй отключить флаги оптимизации. В 2010 студии есть ошибки с этим.
     
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.