Разница в распределении памяти в WIn 7 / Vista по сравнению с WinXP / Win2k3 в следующем коде - PullRequest
0 голосов
/ 01 июля 2010

У меня есть следующий кусок кода. Это написано для получения списка часовых поясов из реестра и заполнения в массив. Этот кусок кода прекрасно работает в ОС Win7 и Vista, но не в WinXp и Win2k3.

Причина в том, что размер массива переполняется. Я определил только 100 элементов. Однако в реестре более 100 элементов.

Теперь мой вопрос: почему это не дает сбоя на компьютерах с Vista или Win7? Есть ли разница в распределении памяти между ОС Xp и Vista.

Вылетает в строке при получении 100 элемента из реестра

while( RegEnumKeyEx( Key, nTimezones, tzKeyNames[nTimezones].GetBuffer( size ), &size, NULL, NULL, NULL, NULL ) != ERROR_NO_MORE_ITEMS )

Полный код

 CString    sRegKey;
    HKEY    Key;
    HKEY    subKey;
    int     nTimezones = 0;
    CArray< CString, CString >  tzKeyNames;

tzOffset.SetSize( 100, 10 );
tzKeyNames.SetSize( 100, 10 );
tzDisplayNames.SetSize( 100, 10 );

OSVERSIONINFO osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
GetVersionEx(&osvi);

if( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT )
{
sRegKey = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones");
}
else
{
sRegKey = _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Time Zones");
}

if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, sRegKey, 0, KEY_READ , &Key ) == ERROR_SUCCESS )
{
    DWORD size;
    DWORD type = REG_SZ;
    TZINFO  tz;
    _TCHAR name[ 128 ];
    BYTE data[ 128 ];

    size = 128;
    while( RegEnumKeyEx( Key, nTimezones, tzKeyNames[nTimezones].GetBuffer( size ), &size, NULL, NULL, NULL, NULL ) != ERROR_NO_MORE_ITEMS )
    {
        tzKeyNames[nTimezones].ReleaseBuffer();

        if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, sRegKey + _T("\\") + (LPCTSTR)tzKeyNames[nTimezones], 0, KEY_READ , &subKey ) == ERROR_SUCCESS )
        {
            size = 128;
            if( RegQueryValueEx( subKey, _T("Display"), NULL, &type, (unsigned char*)name, &size ) == ERROR_SUCCESS )
            {
                tzDisplayNames[nTimezones] = name;
            }

            size = 128;
            if( RegQueryValueEx( subKey, _T("TZI"), NULL, &type, data, &size ) == ERROR_SUCCESS )
            {
                memcpy( &tz, data, size );
                tzOffset[ nTimezones ] = (int)(( tz.Bias / -60.0 ) * 2.0 ) + 24;
            }
            RegCloseKey( subKey );      
        }
        nTimezones++;
    }
    RegCloseKey( Key );     
}

1 Ответ

1 голос
/ 01 июля 2010

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

// РЕДАКТИРОВАНИЕ

tzKeyNames[nTimezones].ReleaseBuffer();

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...