Я получаю следующую ошибку:
"Возникло исключение 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 нет ошибок версия!
Генерирует совершенно другой код сборки.