История одного бага в VC++
От: AIDS Великобритания  
Дата: 20.02.05 22:19
Оценка:
Мы разрабатываем многоплатформенный продукт
(поддерживаются Win32, Mac, Linux, FreeBSD, AIX, Solaris, HP-UX, OS-400).
Все началось с того, что меня озадачили поддержкой больших (>2GB) файлов.
Для этого все действия с file offsets должны осуществляться с 64-битными целыми.
К счастью мы использовали специальный тип FILE_OFF для этого.
Я переопределил этот тип как long long int для Unix'ов и как __int64 для Visual C++ 6.0

Для Unix'ов никаких особых проблем не было. VC++ это убило
Оказалось, что когда какой-нибудь класс содержит член типа __int64
и используется как параметр шаблона, компилятор генерирует неверные адреса членов класса.
И тогда простейшие операции, типа
void SetValue( void* value ) { m_pValue = value; }

не выполняются Т.е. адрес value пишется куда-то внутри объекта, но не в
m_pValue.
Причем место, где подобная ошибка возникает, может меняться
от компиляции к компиляции.
Методом тыка выяснилось, что если поменять structure packing
с 8 byte (по умолчанию) на 4 byte (/Zp4), то проблема исчезает.
Эта же проблема присутствует и VC++ 7.1 (.Net 2003)

К сожалению смена structure packing убило производительность
на 40%
Пришлость реализовать грязный хак:
class CFileOffset
{
private:
   DWORD m_pad[2];
public:
   #define FILE_PROLOG FILE_OFF& m_value = (FILE_OFF&)(*(FILE_OFF*)&m_pad);

   // Все остальные методы - конструкторы, арифметические операции, операторы приведения.
   // Все методы начинаются FILE_PROLOG макро и затем используют переменную m_value
   // для вычислений.
};

Для этого класса компилятор генерирует код идентичный использованию __int64.
/Zp теперь 8 и производительность опять на прежнем уровне.

За недостатком времени я не смог построить минимальный пример, чтобы отправить его
в Microsoft.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.