Ошибка оптимизациии кода в MSVS 2010
От:
Sunzer
Дата: 17.05.11 08:14
Оценка:
Изначальная тема:
http://blablabla.xakep.ru/m_2396461/tm.htm
Вот сорец:
http://dl.dropbox.com/u/22509984/EpicFail.cpp (4 кб)
#define INVALID_HANDLE 0xFFFFFFFF
#define RES_HANDLE_BASE 0x80000000
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
struct ResTable
{
bool Lock;
bool Align;
byte InitSize;
DWORD Size;
DWORD Offset;
int MHandle;
} ResTable[100];
DWORD TablePos, ResCount, TableSize, RandSeed = 1;
byte *Table;
unsigned int Random(DWORD seed)
{
RandSeed = 134775813 * RandSeed + 1;
return (DWORD)RandSeed * (long long)seed >> 32;
}
DWORD AlignValue(DWORD Value, DWORD Alignment)
{
return (Value % Alignment != 0) ? Value += Alignment - (Value % Alignment) : Value;
}
void foo(DWORD Value, DWORD Size)
{
byte Reserved;
if(TablePos + Size > TableSize)
{
TableSize *= 2;
Table = (byte*) realloc(Table, TableSize);
}
switch(Size)
{
case 1: {
Table[TablePos] = Value;
TablePos += Size;
return;
}
case 2: {
*(PWORD) &Table[TablePos] = Value;
TablePos += Size;
return;
}
case 3: {
Reserved = Table[TablePos+4];
*(PDWORD) &Table[TablePos] = Value;
Table[TablePos+3] = Reserved;
TablePos += Size;
return;
}
case 4: {
*(PDWORD) &Table[TablePos] = Value;
TablePos += Size;
return;
}
default: printf("bad input size!\n"); getchar();
}
}
DWORD MemoryAlloc(DWORD Size)
{
DWORD i;
/* Сначало пытаемся найти место в свободных ячейках выше, если нет то выделяем новую */
for(i=0;i<ResCount;i++) if(ResTable[i].Lock == false)
{
if(ResTable[i].InitSize + Size <= 4 && Size != 2)
{
ResTable[ResCount].Offset = ResTable[i].Offset + ResTable[i].InitSize;
ResTable[ResCount].Size = Size;
ResTable[ResCount].Lock = true;
ResTable[ResCount].MHandle = i;
ResTable[ResCount].Align = false;
ResTable[i].Align = false;
ResTable[i].InitSize += Size;
return RES_HANDLE_BASE + ResCount++;
}
}
{
ResTable[ResCount].Size = Size;
ResTable[ResCount].MHandle = -1;
ResTable[ResCount].Offset = ~Size;
switch(Size) {
case 1: ResTable[ResCount].Offset -= 2;
ResTable[ResCount].Align = true;
ResTable[ResCount].InitSize = 1;
break;
case 2: ResTable[ResCount].Offset -= 1;
ResTable[ResCount].Align = true;
ResTable[ResCount].InitSize = 4;
break;
case 4: ResTable[ResCount].Offset += 1;
ResTable[ResCount].Align = false;
ResTable[ResCount].InitSize = 4;
break;
default: ResTable[ResCount].Offset += 1;
ResTable[ResCount].Align = true;
ResTable[ResCount].InitSize = 4;
break;
}
for(i=0;i<ResCount;i++) if(ResTable[i].MHandle == -1) ResTable[ResCount].Offset -= AlignValue(ResTable[i].Size, 4);
return RES_HANDLE_BASE + ResCount++;
}
return INVALID_HANDLE;
}
DWORD LocalVarAddr(DWORD Handle)
{
return ResTable[Handle - RES_HANDLE_BASE].Offset;
}
DWORD LocalVarSize(DWORD Handle)
{
return ResTable[Handle - RES_HANDLE_BASE].Size;
}
void FailFunc(DWORD Handle, BYTE V2)
{
DWORD Offset, Size;
if(Handle >= RES_HANDLE_BASE)
{
Offset = LocalVarAddr(Handle);
Size = LocalVarSize(Handle);
if(~Offset < 0x80)
{
switch(Size)
{
case 1: foo(0,3); break;
case 2: foo(0,4); break;
case 4: foo(0,3); break;
default:printf("Size = %d\nFail found #1\n", Size); getchar();
}
foo(Offset,1);
}
else
{
switch(Size)
{
case 1: foo(0,2); break;
case 2: foo(0,3); break;
case 4: foo(0,2); break;
default:printf("Size = %d\nFail found #2\n", Size); getchar();
}
foo(Offset,4);
}
}
else
{
printf("Debug test\n");
}
}
int main(int argc, char *argv[])
{
RandSeed = 0xC0DEC0DE;
TablePos = 0;
TableSize = 0x100000; // 1MB
Table = (byte*) calloc(TableSize, 1);
FailFunc(MemoryAlloc(1), 0);
return 0;
}
Visual Studio 2010 Express
Флаги компиляции (стандартные, изменены только оптимизация по размеру кода и все):
/Zi /nologo /W3 /WX- /MP /O1 /Oi /Os /Oy- /GL /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /GF /Gm- /EHsc /MT /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fp"Release\EpicFail.pch" /Fa"Release\" /Fo"Release\" /Fd"Release\vc100.pdb" /Gd /analyze- /errorReport:queue
Вывод программы:
Size = 1
Fail found #1
дизасм:
[image]
http://dl.dropbox.com/u/22509984/epic.PNG [/image]
Re: Ошибка оптимизациии кода в MSVS 2010
От:
uzhas
Дата: 17.05.11 08:25
Оценка:
+1
Здравствуйте, Sunzer, Вы писали:
S>Изначальная тема: http://blablabla.xakep.ru/m_2396461/tm.htm
S>Вот сорец: http://dl.dropbox.com/u/22509984/EpicFail.cpp (4 кб)
а переменную ResCount не следует проинициализировать? да и смелые ResCount++ настораживают. следить за выходами из диапазона надо
Re: Ошибка оптимизациии кода в MSVS 2010
Здравствуйте, Sunzer, Вы писали:
1. хорошо бы научиться правильно форматировать ccode вместо code
2. отсутствие инициализации вроде как не помеха ошибки
3. всевдо-код смотреть только зрение портить
4. ошибка видмо в этой части. Size и Offset доходят правильными (т.е. все остальное можно выкинуть)
if (~Offset < 0x80)
{
switch (Size)
{
case 1: foo(0,3); break ;
который транслируется в
if (~Offset < 0x80)
01181172 8B CE mov ecx ,esi
01181174 F7 D1 not ecx
01181176 81 F9 80 00 00 00 cmp ecx ,80h
{
switch(Size )
0118117C 8B C8 mov ecx ,eax
0118117E 49 dec ecx
0118117F 57 push edi
01181180 73 30 jae FailFunc+51h (11811B2h)
01181182 49 dec ecx
01181183 74 1A je FailFunc+3Eh (118119Fh)
01181185 49 dec ecx
01181186 49 dec ecx
01181187 74 1A je FailFunc+42h (11811A3h)
такое подозрение, что тут лишний раз генерят dec ecx (первый или второй)
5. было бы хорошо. если бы уменьшили пример и послали в MS.
---
С уважением,
Сергей Мухин
Re: Ошибка оптимизациии кода в MSVS 2010
Здравствуйте, Sunzer, Вы писали:
и еще. когда пишете о возможных ошибках компилятора, указывайте версию полностью. А 2010 этого мало.
я проверял на
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
---
С уважением,
Сергей Мухин
Re: Ошибка оптимизациии кода в MSVS 2010
От:
Abyx
Дата: 17.05.11 08:57
Оценка:
+4
Здравствуйте, Sunzer, Вы писали:
S>Вот сорец: http://dl.dropbox.com/u/22509984/EpicFail.cpp (4 кб)
приведите *минимальный* код, воспроизводящий ошибку, компилирующийся с опциями компилятора /W4 /WX
In Zen We Trust
Re: Ошибка оптимизациии кода в MSVS 2010
От:
Sunzer
Дата: 17.05.11 12:58
Оценка:
Я написал минимальный код воспроизводящий ошибку. 4 кб это очень много?
Компилятор самый последний с сайта MS. Express 2010. Опции компиляции выше. Инициализация ResCount не рашеает проблему, к тому же страницы памяти инициализируются нулями.
На старой студии 2008 тоже ошибка проявляется.
10.0.30319.1
Re: Ошибка оптимизациии кода в MSVS 2010
От:
Sunzer
Дата: 17.05.11 13:11
Оценка:
Пожалуйста вот код, который по прежнему работает не правильно при /WX /W4
#define INVALID_HANDLE 0xFFFFFFFF
#define RES_HANDLE_BASE 0x80000000
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
struct ResTable
{
bool Lock;
bool Align;
byte InitSize;
DWORD Size;
DWORD Offset;
int MHandle;
} ResTable[100];
DWORD TablePos, ResCount, TableSize, RandSeed = 1;
byte *Table;
unsigned int Random(DWORD seed)
{
RandSeed = 134775813 * RandSeed + 1;
return (DWORD)RandSeed * (long long )seed >> 32;
}
DWORD AlignValue(DWORD Value, DWORD Alignment)
{
return (Value % Alignment != 0) ? Value += Alignment - (Value % Alignment) : Value;
}
void foo(DWORD Value, DWORD Size)
{
byte Reserved;
if (TablePos + Size > TableSize)
{
TableSize *= 2;
Table = (byte*) realloc(Table, TableSize);
}
switch (Size)
{
case 1: {
Table[TablePos] = (BYTE)Value;
TablePos += Size;
return ;
}
case 2: {
*(PWORD) &Table[TablePos] = (WORD)Value;
TablePos += Size;
return ;
}
case 3: {
Reserved = Table[TablePos+4];
*(PDWORD) &Table[TablePos] = Value;
Table[TablePos+3] = Reserved;
TablePos += Size;
return ;
}
case 4: {
*(PDWORD) &Table[TablePos] = Value;
TablePos += Size;
return ;
}
default : printf("bad input size!\n" ); getchar();
}
}
DWORD MemoryAlloc(DWORD Size)
{
DWORD i;
/* Сначало пытаемся найти место в свободных ячейках выше, если нет то выделяем новую */
for (i=0;i<ResCount;i++) if (ResTable[i].Lock == false )
{
if (ResTable[i].InitSize + Size <= 4 && Size != 2)
{
ResTable[ResCount].Offset = ResTable[i].Offset + ResTable[i].InitSize;
ResTable[ResCount].Size = Size;
ResTable[ResCount].Lock = true ;
ResTable[ResCount].MHandle = i;
ResTable[ResCount].Align = false ;
ResTable[i].Align = false ;
ResTable[i].InitSize += (BYTE)Size;
return RES_HANDLE_BASE + ResCount++;
}
}
{
ResTable[ResCount].Size = Size;
ResTable[ResCount].MHandle = -1;
ResTable[ResCount].Offset = ~Size;
switch (Size) {
case 1: ResTable[ResCount].Offset -= 2;
ResTable[ResCount].Align = true ;
ResTable[ResCount].InitSize = 1;
break ;
case 2: ResTable[ResCount].Offset -= 1;
ResTable[ResCount].Align = true ;
ResTable[ResCount].InitSize = 4;
break ;
case 4: ResTable[ResCount].Offset += 1;
ResTable[ResCount].Align = false ;
ResTable[ResCount].InitSize = 4;
break ;
default : ResTable[ResCount].Offset += 1;
ResTable[ResCount].Align = true ;
ResTable[ResCount].InitSize = 4;
break ;
}
for (i=0;i<ResCount;i++) if (ResTable[i].MHandle == -1) ResTable[ResCount].Offset -= AlignValue(ResTable[i].Size, 4);
return RES_HANDLE_BASE + ResCount++;
}
}
DWORD LocalVarAddr(DWORD Handle)
{
return ResTable[Handle - RES_HANDLE_BASE].Offset;
}
DWORD LocalVarSize(DWORD Handle)
{
return ResTable[Handle - RES_HANDLE_BASE].Size;
}
void FailFunc(DWORD Handle)
{
DWORD Offset, Size;
if (Handle >= RES_HANDLE_BASE)
{
Offset = LocalVarAddr(Handle);
Size = LocalVarSize(Handle);
if (~Offset < 0x80)
{
switch (Size)
{
case 1: foo(0,3); break ;
case 2: foo(0,4); break ;
case 4: foo(0,3); break ;
default :printf("Size = %d\nFail found #1\n" , Size); getchar();
}
foo(Offset,1);
}
else
{
switch (Size)
{
case 1: foo(0,2); break ;
case 2: foo(0,3); break ;
case 4: foo(0,2); break ;
default :printf("Size = %d\nFail found #2\n" , Size); getchar();
}
foo(Offset,4);
}
}
else
{
printf("Debug test\n" );
}
}
int main()
{
RandSeed = 0xC0DEC0DE;
TablePos = 0;
ResCount = 0;
TableSize = 0x100000; // 1MB
Table = (byte*) calloc(TableSize, 1);
FailFunc(MemoryAlloc(1));
return 0;
}
Re[2]: Ошибка оптимизациии кода в MSVS 2010
От:
Abyx
Дата: 17.05.11 17:17
Оценка:
+1
Здравствуйте, Sunzer, Вы писали:
S>Пожалуйста вот код, который по прежнему работает не правильно при /WX /W4
у меня этот код работает нормально.
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
In Zen We Trust
Re[3]: Ошибка оптимизациии кода в MSVS 2010
Здравствуйте, Abyx, Вы писали:
A>Здравствуйте, Sunzer, Вы писали:
S>>Пожалуйста вот код, который по прежнему работает не правильно при /WX /W4
A>у меня этот код работает нормально.
A>Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
с заявленными опциями?
---
С уважением,
Сергей Мухин
Re[4]: Ошибка оптимизациии кода в MSVS 2010
От:
Abyx
Дата: 17.05.11 18:08
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:
СМ>Здравствуйте, Abyx, Вы писали:
A>>Здравствуйте, Sunzer, Вы писали:
S>>>Пожалуйста вот код, который по прежнему работает не правильно при /WX /W4
A>>у меня этот код работает нормально.
A>>Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
СМ>с заявленными опциями?
хм.. действительно, с заявленными опциями выдает ошибку
In Zen We Trust
Re: Ошибка оптимизациии кода в MSVS 2010
От:
HolyNick
Дата: 18.05.11 08:12
Оценка:
У компилятора Visual Studio 2010 под Win 32 ,похоже, есть проблемы с флагом оптимизации \Og. В данном случае он устанавливается флагом \O1 (см. msdn)
Re[2]: Ошибка оптимизациии кода в MSVS 2010
От:
Sunzer
Дата: 19.05.11 13:24
Оценка:
Ну и что делать с багом?
Re[3]: Ошибка оптимизациии кода в MSVS 2010
От:
HolyNick
Дата: 19.05.11 13:35
Оценка:
Если(что не факт, я не разбирался с твоим кодом) в твоем случае проблема с /Og, то следует попробовать его отключить.
Re[3]: Ошибка оптимизациии кода в MSVS 2010
Здравствуйте, Sunzer, Вы писали:
S>Ну и что делать с багом?
шли авторам, что же еще.
а в программе обойди, это не сложно.
---
С уважением,
Сергей Мухин
Пока на собственное сообщение не было ответов, его можно удалить.
Удалить