2

Мы используем библиотеку SQLite в нашем продукте, и внезапно после перекомпиляции с другой версией компилятора (Visual C++) он начал сбой на клиентских компьютерах.Нарушение права доступа на чтение в инструкции чтения

Грохот является

ExceptionAddress: 0710eadd (sqlite3!sqlite3_transfer_bindings+0x0004e5bd) 
    ExceptionCode: c0000005 (Access violation) 
    ExceptionFlags: 00000000 
NumberParameters: 2 
    Parameter[0]: 00000001 
    Parameter[1]: 07148688 
Attempt to write to address 07148688 

и код причиной аварии является следующая (часть sqlite3MutexInit):

0710ead0 b804811407  mov  eax, 0x07148104 
0710ead5 b97c861407  mov  ecx, 0x0714867c 
0710eada 0f44c8   cmove ecx, eax 
0710eadd f30f7e410c  movq xmm0, mmword ptr [ecx+0Ch] 

Соответствующий код C:

if(sqlite3GlobalConfig.bCoreMutex){ 
    pFrom = sqlite3DefaultMutex(); 
}else{ 
    pFrom = sqlite3NoopMutex(); 
} 
memcpy(pTo, pFrom, offsetof(sqlite3_mutex_methods, xMutexAlloc)); 

Это не особенно важно, но в нашем случае sqlite3GlobalConfig.bCoreMutex установлен в 1.

Проблема в том, что в этом конкретном случае память по адресу 07148688 читается и инструкция должна читать это, а не писать.

У нас есть дампы памяти с двух компьютеров, и в обоих случаях это происходило на процессорах Athlon XP (Family/Model/Stepping: 6/10/0, 6/8/1).

Перекомпиляция с несколькими версиями Visual C++ (обновление 2012, 2013 и 2013 гг.) Yeilds немного отличается от кода (команда movq vs movdqu на адрес сбоя), но авария происходит последовательно.

Может ли это быть вызвано ошибкой процессора или компилятора, с которой мы сталкиваемся?

+0

Нарушение прав доступа при чтении происходит, когда вы пытаетесь прочитать местоположение на странице охраны. Скорее всего, это индекс из связанной проблемы. Я предлагаю вам отладить исключение и посмотреть, что находится в том месте, где исключение говорит о нарушении. – Mgetz

+0

Доступный адрес - это таблица указателей в сгенерированном коде, и адрес является правильным и читаемым. Я даже подтвердил это в отладчиках и посмертных отвалах. Проблема в том, что исключение - это нарушение * записи * доступа, но инструкция должна * читать *. Адрес не доступен для записи, кстати. –

ответ

3

Более старые процессоры AMD Athlon (и Pentium III), по-видимому, не поддерживают эту форму movq, которая была введена с инструкциями SSE2. Цитирую Anders Carlsson в GCC discussion:

Глядя на справочной документации Intel доступной из ftp://download.intel.com/design/Pentium4/manuals/25366614.pdf MOVQ имеет следующие опкоды:

0F 6F /r MOVQ mm, mm/m64  Move quadword from mm/m64 to mm. 
0F 7F /r MOVQ mm/m64, mm  Move quadword from mm to mm/m64. 
F3 0F 7E MOVQ xmm1, xmm2/m64 Move quadword from xmm2/mem64 to xmm1. 
66 0F D6 MOVQ xmm2/m64, xmm1 Move quadword from xmm1 to xmm2/mem64. 

и поскольку два последних инструкций не поддерживаются на AMD и Pentium III вас потребуется другой способ перемещения данных между xmm-регистрами и памятью.

Эта справочная документация Intel больше не доступна; другая ссылка для команды movq находится на http://x86.renejeschke.de/html/file_module_x86_id_201.html. Тем не менее, у меня нет AMD Athlon XP, чтобы проверить это.

Отказ от оптимизации SSE2 должен решить проблему. Набор инструкций SSE2 является значением по умолчанию в VS2012 и более поздних версиях, а флаг компилятора/arch управляет тем, какая команда должна использоваться; см. http://msdn.microsoft.com/en-us/library/7t5yh4fd%28v=vs.110%29.aspx.

+0

Я раньше смотрел руководства к процессору, и я был очень уверен, что инструкция SSE, а не SSE2, которая должна поддерживаться на процессорах Athlon XP.Однако теперь, когда вы указали, что версия XMM является SSE2, она имеет смысл. –