Нарушение Visual Studio Access Ошибка в выпуске x64 с оптимизацией по умолчанию - PullRequest
0 голосов
/ 06 февраля 2020

Я получаю следующую ошибку:
"Возникло исключение 0x00007FF7998111B4 в BugTest.exe: 0xC0000005: Место записи нарушения прав доступа 0x000000F6C37B3198."
только для x64 выпуска версия

Я думаю, что это связано с оптимизацией по умолчанию. При отключении оптимизации по умолчанию ошибки не возникает.
Версия visual studio: VS 14.0.25431.01 Обновление 3

Я создаю проект следующим образом:

Файл -> Новый -> Проект ->
Visual C ++ -> Win32 -> Консольное приложение Win32 ->
Настройки приложения -> [ПРОВЕРИТЬ] Пустой проект -> Fini sh
Обозреватель решений -> Исходные файлы -> Добавить -> Существующий элемент ...

Это глупый, бессмысленный пример гораздо более крупного проекта.
Он был максимально очищен, чтобы могла возникнуть ошибка.

#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <stdio.h>

typedef enum {
    CAR_BMW     = 10, CAR_KIA, CAR_LEXUS, CAR_ISUZU,
    CAR_CITROEN = 50, CAR_MAZDA, CAR_FERRARI, CAR_JEEP, CAR_NISSAN,
    CAR_AUDI    = 90, CAR_DACIA, CAR_HYUNDAI, CAR_OPEL
} cars_codes;

typedef struct {
    char brand[64];
    int car_code;
} sCAR;

#define MAX_CARS_PER_GROUP        16
static sCAR* cars[ MAX_CARS_PER_GROUP ];
static unsigned int cars_count = 0;

static const sCAR  car_group[] = {
    { "ISUZU"            , CAR_ISUZU },
    { "LEXUS"            , CAR_LEXUS },
    { "BMW"              , CAR_BMW },
    { "KIA"              , CAR_KIA },
    { "DACIA"            , CAR_DACIA },
    { "AUDI"             , CAR_AUDI },
    { "HYUNDAI"          , CAR_HYUNDAI },
    { "OPEL"             , CAR_OPEL },
    { "CITROEN"          , CAR_CITROEN },
    { "MAZDA"            , CAR_MAZDA },
    { "FERRARI"          , CAR_FERRARI },
    { "JEEP"             , CAR_JEEP },
    { "NISSAN"           , CAR_NISSAN },
    { "", 0 }
};

int get_car_name( int car_code, char *brand ) {
    int rv = 0;
    printf( "%s( %d, 0x%p )", __FUNCTION__, car_code, brand );
    for( unsigned int i = 0; i < cars_count; i++ ) {
        if( cars[i]->car_code == car_code ) {
            strcpy(brand, cars[i]->brand);
            rv = 1;
            break;
        }
    }
    printf( " returns %d\n", rv );
    return rv;
}

void main( void ) {
    int current_cars[ ] =  { CAR_DACIA, CAR_OPEL, CAR_CITROEN, CAR_MAZDA, CAR_JEEP, CAR_NISSAN };
    char b_name[ 32 ];
    unsigned int i;

    for( i = 0; i < MAX_CARS_PER_GROUP; i++ ) {
        if( !car_group[ i ].car_code ) break;
        cars[ i ] = new sCAR( );
        strcpy( cars[ i ]->brand, car_group[ i ].brand );
        cars[ i ]->car_code = car_group[ i ].car_code;
    }
    cars_count = i;

    for( i = 0; i < _countof( current_cars ); i++ ) {
        printf( "i = %d\n", i );
        if( get_car_name( current_cars[ i ], b_name ) ) {
            printf( "%s\n\n", b_name );
        }
    }

    for( i = 0; i < cars_count; delete cars[ i++ ] );
}

Программа печатает следующее и умирает:
i = 0
get_car_name( 91, 0x000000F6C37AF8B8 )

Я думаю, что оптимизация неверно рассчитывает адрес, потому что неправильный адрес:
0x000000F6C37B3198

Он рассчитывается следующим образом (я также даю код сборки):

            if( get_car_name( current_cars[ i ], b_name ) ) {
00007FF79981115E  mov         ebx,dword ptr [r14]               // r14 = 0x000000f6c37af8a0
00007FF799811161  lea         r9,[b_name]                   // b_name = 0x000000f6c37af8b8 ""
00007FF799811166  mov         r8d,ebx  
00007FF799811169  lea         rdx,[string "get_car_name" (07FF7998132C8h)]  
00007FF799811170  lea         rcx,[string "%s( %d, 0x%p )" (07FF7998132D8h)]  
00007FF799811177  mov         edi,esi  
00007FF799811179  call        printf (07FF799811010h)  
00007FF79981117E  mov         r8d,dword ptr [cars_count (07FF7998156C0h)]  
00007FF799811185  mov         edx,esi  
00007FF799811187  test        r8d,r8d  
00007FF79981118A  je          main+154h (07FF7998111C4h)  
00007FF79981118C  mov         rcx,r15  
00007FF79981118F  nop  
00007FF799811190  mov         rax,qword ptr [rcx]  
00007FF799811193  cmp         dword ptr [rax+40h],ebx  
00007FF799811196  je          main+135h (07FF7998111A5h)  
00007FF799811198  inc         edx  
00007FF79981119A  add         rcx,8  
00007FF79981119E  cmp         edx,r8d  
00007FF7998111A1  jb          main+120h (07FF799811190h)  
00007FF7998111A3  jmp         main+154h (07FF7998111C4h)  
00007FF7998111A5  lea         rdx,[b_name]  
00007FF7998111AA  sub         rdx,qword ptr [cars (07FF7998156D0h)]  
00007FF7998111B1  movzx       ecx,byte ptr [rax]
// --- Access violation writing location 0x000000F6C37B3198:
00007FF7998111B4  mov         byte ptr [rdx+rax],cl // rdx = 0xfffffe4a99a95cc8, rax = 0x000002ac29d1d4d0, cl ='D'
// -----------------------------------------------------
00007FF7998111B7  lea         rax,[rax+1]  
00007FF7998111BB  test        cl,cl  
00007FF7998111BD  jne         main+141h (07FF7998111B1h)  
00007FF7998111BF  mov         edi,1  
00007FF7998111C4  mov         edx,edi  
00007FF7998111C6  lea         rcx,[string " returns %d\n" (07FF7998132E8h)]  
00007FF7998111CD  call        printf (07FF799811010h)  
00007FF7998111D2  test        edi,edi  
00007FF7998111D4  je          main+177h (07FF7998111E7h)  
            printf( "%s\n\n", b_name );

Моя проблема в том, что я не могу предотвратить эту ошибку. Плохо то, что когда я использую printf для лучшего прояснения ситуации, ошибка исчезает!

Позже я проверил другую версию Visual Studio:
В Visual Studio 2008 версии 9.0.21022.8 RTM нет ошибок версия!
Генерирует совершенно другой код сборки.

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