2013-09-13 3 views
1

У меня есть проект DLL, который обеспечивает определение типа с Delphi «вариантная частью» следующим образом:неправильного размера структуры, когда Variant Часть, используемая в записях

type TValue = record 
case Kind : cardinal of 
valueShortCard : (ValShortCard : byte); 
valueLongReal : (ValLongReal : double); 
end; 

я ожидаю, что эта структура будет иметь размер 12 байт (4B для кардинала плюс 8B для двойного, так как это больше из этих двух типов).

Но если у меня есть приложение и вызывается функция sizeof() для структуры в DLL, в нем указано, что размер составляет 16 байт.

Кроме того, если я объявляю ту же структуру непосредственно в проекте приложения .exe, sizeof() возвращает правильный размер 12 байтов.

Если я запустил приложение и попытаюсь получить значение ValLongReal из скомпилированной библиотеки DLL, возвращаемое значение неверно и кажется, что оно смещено на 4 байта в памяти.

I.E. если «двойная» переменная в DLL отображает значение «40 45 9a e1 47 ae 14 7b» (интерпретируется в байтовых значениях), значение, возвращаемое приложением после чтения из DLL, равно «47 ae 14 7b 77 07 06 7d ". Это означает, что есть 4 байта перекрытия правильных данных, а последние 4 байта являются неправильными и считываются из следующего пространства в памяти.

Примечание: Такое поведение наблюдается уже в Delphi XE4, мы только что обновили его до XE5, но он ведет себя одинаково. Используемая ОС - 32-разрядная версия Win7.

спасибо за ваши предложения

+2

Зависит от настроек компилятора для выравнивания. –

ответ

3

определить его как таковой:

type TValue = packed record 
    case Kind : cardinal of 
    valueShortCard : (ValShortCard : byte); 
    valueLongReal : (ValLongReal : double); 
    end; 

Здесь sizeof(TValue)=12, как вы ожидали.

Добавление packed record принудительное выравнивание силы. Если нет выравнивания, double будет выровняться по границам 8 байтов, поэтому Kind будет использовать 8 байтов вместо 4, а valueLongReal также, следовательно, sizeof(TValue)=8+8=16 в вашем случае.

Обратите внимание, что под Win64 вам необходимо установить , чтобы выровнять double переменных. И это всегда хорошая идея по соображениям производительности.

Обратите внимание, что изменение параметров записи изменилось с помощью Delphi XE3 AFAIR в отношении предыдущих версий.

+0

Вам нужно выровнять удвоения на x64? Я не думал, что компилятор издает инструкции SSE, которые требуют выравнивания. Вы должны выровнять их, если вы используете библиотеки, такие как GR32, которые используют выровненные инструкции. Я также думаю, что ответ, возможно, немного вводит в заблуждение. Из первого предложения, похоже, вы выступаете за упаковку. Я знаю, что ты никогда этого не сделаешь. –

+0

Он не будет создавать исключение CPU, так как в архитектуре x64 исключения выравнивания по умолчанию отключены, а исправления выполняются аппаратным обеспечением. Но это будет намного медленнее. По умолчанию компилятор пытается выровнять каждое двойное значение, и мы всегда должны придерживаться его! Таким образом, вы * нуждаетесь * для выравнивания по причинам производительности и согласованности. –

+0

То же самое верно и для x86. Mis-align удваивает и это кошмар. Старые версии Delphi сделали это, выровняв границы не более, чем на 4 байта. –

 Смежные вопросы

  • Нет связанных вопросов^_^