Я испытываю странные сбои. И я задаюсь вопросом, является ли это ошибкой в моем коде или компиляторе. Когда я компилирую следующий код на С++ с Microsoft Visual Studio 2010 в качестве оптимизированной сборки выпуска, он падает в отмеченной строке:
struct tup { int x; int y; };
class C
{
public:
struct tup* p;
struct tup* operator--() { return --p; }
struct tup* operator++(int) { return p++; }
virtual void Reset() { p = 0;}
};
int main ()
{
C c;
volatile int x = 0;
struct tup v1;
struct tup v2 = {0, x};
c.p = &v1;
(*(c++)) = v2;
struct tup i = (*(--c)); // crash! (dereferencing a NULL-pointer)
return i.x;
}
Взглянув на разборку, очевидно, что он должен сработать:
int _tmain(int argc, _TCHAR* argv[])
{
00CE1000 push ebp
00CE1001 mov ebp,esp
00CE1003 sub esp,0Ch
C c;
volatile int x = 0;
00CE1006 xor eax,eax
00CE1008 mov dword ptr [x],eax
struct tup v1;
struct tup v2 = {0, x};
00CE100B mov ecx,dword ptr [x]
c.p = &v1;
(*(c++)) = v2;
00CE100E mov dword ptr [ebp-8],ecx
struct tup i = (*(--c));
00CE1011 mov ecx,dword ptr [x]
00CE1014 mov dword ptr [v1],eax
00CE1017 mov eax,dword ptr [ecx]
00CE1019 mov ecx,dword ptr [ecx+4]
00CE101C mov dword ptr [ebp-8],ecx
return i.x;
}
00CE101F mov esp,ebp
00CE1021 pop ebp
00CE1022 ret
При смещении 00CE1008 он записывает 0 в x.
При смещении 00CE100B он считывает x (0) в ecx
При смещении 00CE1017 это разыгрывает то, что 0-указатель.
Я вижу две возможные причины:
-
В моем коде есть какой-то тонкий (или не такой тонкий?) случай поведения undefined и компилятор "оптимизирует" это поведение undefined в результате сбоя.
-
или есть ошибка компилятора
Кто-нибудь видит, что может вызвать проблему?
Спасибо,
Джонас
РЕДАКТИРОВАТЬ: Чтобы ответить на комментарии относительно "указателя на недопустимое местоположение"
Если я изменил v1
на struct tup v1[10];
и установил c.p = &v1[0];
, тогда не будет указателя на недопустимое местоположение. Но я все еще могу наблюдать такое же поведение. Разборки выглядят незначительно по-разному, но по-прежнему происходит сбой, и он все еще вызван загрузкой 0 в ecx и разыменованием его.
EDIT: Заключение
Итак, возможно, это ошибка. Я узнал, что авария исчезает, если я изменяю
struct tup* operator--() { return --p; }
к
struct tup* operator--() { --p; return p; }
Как сообщает bames53, авария не возникает в VS2011 и приходит к выводу, что она должна быть исправлена.
Тем не менее, я решил записать эту ошибку по двум причинам:
-
Ошибка может по-прежнему присутствовать в VS2011. Возможно, оптимизатор просто изменился так, что мой код больше не вызывает ошибку. (ошибка кажется очень тонкой, она не возникает, когда я удаляю
volative
илиvirtual void Reset()
) -
Я хочу знать, может ли мой обходной путь надежным способом исключить сбои или если изменения кода в других местах могут повторно ввести ошибку.
Вот ссылка:
https://connect.microsoft.com/VisualStudio/feedback/details/741628/error-in-code-generation-for-x86