крешится mktime()
От: sushko Россия  
Дата: 02.08.06 10:42
Оценка: -1
Hi, All!

У некоторых (очень редких) пользователей падает _примерно_ вот такой код:

tm theTime;
ZeroMemory(&theTime, sizeof(theTime));
theTime.tm_sec=0 ;
theTime.tm_min=0 ;
theTime.tm_hour=10 ;
theTime.tm_mday=1 ;
theTime.tm_year=70 ;
theTime.tm_wday=0 ;
theTime.tm_yday=0 ;
theTime.tm_isdst=-1;
DWORD dwBuffer = mktime(&theTime);

Текст ашипки:

AppName: test.exe AppVer: 0.0.0.0 ModName: msvcrt.dll
ModVer: 7.0.2600.2180 Offset: 0003ae80

Причем падает оно именно на mktime. Приложение — VC++ 6.0 / MFC, операционка у пользователя, судя по всему, XP. Пойти на компьютер пользователя и посмотреть, что происходит, не получается из-за физической удаленности (Австралия); у нас у самих не воспроизводится.

Что может быть не так? Исходники тестового проекта (там код немножко не такой, в этом сообщении я упростил для лучшего восприятия) на www.sushko.ru/mktime.zip (23K).



04.08.06 02:34: Перенесено модератором из 'C/C++' — Павел Кузнецов
Бесплатный генератор отчетов для программ на C/C++
http://www.oxetta.com
Re: крешится mktime()
От: Alexey Frolov Беларусь  
Дата: 02.08.06 15:43
Оценка:
Здравствуйте, sushko, Вы писали:

S>Причем падает оно именно на mktime.

А каким образом удалось выяснить что именно на mktime и никак иначе?
Re: крешится mktime()
От: Alexey Frolov Беларусь  
Дата: 02.08.06 16:00
Оценка: 87 (6) +1
Здравствуйте, sushko, Вы писали:

S>Причем падает оно именно на mktime. Приложение — VC++ 6.0 / MFC, операционка у пользователя, судя по всему, XP. Пойти на компьютер пользователя и посмотреть, что происходит, не получается из-за физической удаленности (Австралия); у нас у самих не воспроизводится.


Видел код, в подробности не вдавался, но скомпилял, запустил. Ничего не падает в обычном режиме, ни debug ни release, ни на xp, ни на 2k3. Но поменяв на xp часовой пояс на +10 melburne sydney, тут же получил падение. На 2k3 такого эффекта не было. Так что меняйте пояс на xp и дебаггер в зубы. Удачи. Отпишите чем эпопея закончится, интересно все таки в чем дело
Re: крешится mktime()
От: landerhigh Пират  
Дата: 02.08.06 23:20
Оценка:
Здравствуйте, sushko, Вы писали:

S>Hi, All!


S>У некоторых (очень редких) пользователей падает _примерно_ вот такой код:


S>tm theTime;

S>ZeroMemory(&theTime, sizeof(theTime));
S>theTime.tm_sec=0 ;
S>theTime.tm_min=0 ;
S>theTime.tm_hour=10 ;
S>theTime.tm_mday=1 ;
S>theTime.tm_year=70 ;
S>theTime.tm_wday=0 ;
S>theTime.tm_yday=0 ;
S>theTime.tm_isdst=-1;
S>DWORD dwBuffer = mktime(&theTime);

Фул стоп.
Я правильно понимаю, что это 70 год?
А на других годах не падает?
У меня линух, так что проверить на месте не смогу, но есть подозрение, что т.к. (месяц-то кстати, какой?) в январе тут как раз лето, то в абсолюте с Гривичем получается 11 часов разницы, т.е. возможно что-то в недрах виндовса вылезает в 69 год, чему несказанно удивляется и падает нафиг
www.blinnov.com
Re[2]: крешится mktime()
От: sushko Россия  
Дата: 03.08.06 08:21
Оценка:
Здравствуйте, Alexey Frolov, Вы писали:

S>>Причем падает оно именно на mktime. Приложение — VC++ 6.0 / MFC, операционка у пользователя, судя по всему, XP. Пойти на компьютер пользователя и посмотреть, что происходит, не получается из-за физической удаленности (Австралия); у нас у самих не воспроизводится.


AF>Видел код, в подробности не вдавался, но скомпилял, запустил. Ничего не падает в обычном режиме, ни debug ни release, ни на xp, ни на 2k3. Но поменяв на xp часовой пояс на +10 melburne sydney, тут же получил падение. На 2k3 такого эффекта не было. Так что меняйте пояс на xp и дебаггер в зубы. Удачи. Отпишите чем эпопея закончится, интересно все таки в чем дело


Ага, точно, после смены часового пояса release на XP падает как часы . Спасибо! Будем разбираться; результат обязательно сообщу
Бесплатный генератор отчетов для программ на C/C++
http://www.oxetta.com
Re[3]: крешится mktime()
От: Andrew S Россия http://alchemy-lab.com
Дата: 03.08.06 19:46
Оценка: 64 (7)
S>>>Причем падает оно именно на mktime. Приложение — VC++ 6.0 / MFC, операционка у пользователя, судя по всему, XP. Пойти на компьютер пользователя и посмотреть, что происходит, не получается из-за физической удаленности (Австралия); у нас у самих не воспроизводится.

AF>>Видел код, в подробности не вдавался, но скомпилял, запустил. Ничего не падает в обычном режиме, ни debug ни release, ни на xp, ни на 2k3. Но поменяв на xp часовой пояс на +10 melburne sydney, тут же получил падение. На 2k3 такого эффекта не было. Так что меняйте пояс на xp и дебаггер в зубы. Удачи. Отпишите чем эпопея закончится, интересно все таки в чем дело


S>Ага, точно, после смены часового пояса release на XP падает как часы . Спасибо! Будем разбираться; результат обязательно сообщу


В общем, если кому интересно — бага в crt. Связанная с летним временем. В отличие от почти всех нормальных стран, в Австралии 1.1.1970 неожиданно было ... лето Поэтому crt неправильно считает range и впоследствии вываливается (подробности мне уже было выяснять лениво, поскольку задача фиксить crt не стояла). Примерно там вот что:

78029019 a120e80378       mov     eax,[MSVCRT!_dstbias (7803e820)]
7802901e 014508           add     [ebp+0x8],eax
78029021 8d4508           lea     eax,[ebp+0x8]
78029024 50               push    eax
78029025 e8e4fcffff       call    MSVCRT!localtime (78028d0e)
7802902a 59               pop     ecx
7802902b 6a09             push    0x9
7802902d 8bf0             mov     esi,eax
7802902f 8b4508           mov     eax,[ebp+0x8]
78029032 59               pop     ecx
78029033 f3a5            rep  movsd ds:00000000=???????? es:0012ff04=00000000

В crt это соответствует этому кусочку:
            if ( (tb->tm_isdst > 0) || ((tb->tm_isdst < 0) &&
              (tbtemp->tm_isdst > 0)) ) {
                tmptm1 += _dstbias;
                tbtemp = localtime(&tmptm1);    /* reconvert, can't get NULL */
            }

        }
        else {
            if ( (tbtemp = gmtime(&tmptm1)) == NULL )
                goto err_mktime;
        }

        /***** HERE: tmptm1 holds number of elapsed seconds, adjusted *****/
        /*****       for local time if requested                      *****/

        *tb = *tbtemp;


Соответственно, обламывает всю малину localtime, возвращая NULL, несмотря на горячее пожелание ей не делать этого хлопцев из m$ в комментах. Молодцы, умеют.

Ну и был придуман следующий ход — для даты 1.1.1970 день увеличивался на единичку, затем из результата вычиталось 3600*24 (естественно, с контролем переполнения). Помогло
Кстати, по пути же еще нашлись несколько неприятных багов в дебажных версиях crt — они неправильно летнее время учитывают для различных часовых поясов. Видимо, в более позднем рантайме (релизный рантайм crt вышел гораздо после 6-ки) это дело поправили. А вообще, функции виндовс работы со временем — это просто песня Оказалось, что и они весьма "специфично" работают со временем — например, GetDateFormat\GetTimeFormat и, похоже, вообще все функции работы со временем, считают летнее время не от обрабатываемой даты, а от текущей. В результате получаются феерические эффекты
Спасибо m$, в очередной раз испортили день и отняли веру в прекрасное...
http://www.rusyaz.ru/pr — стараемся писАть по-русски
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.