Изменение размера класса между приложением и exe - PullRequest
4 голосов
/ 17 января 2012

У меня есть консольное приложение, которое создает экземпляр класса (скажем, class X). Класс определяется в dll -> X.dll. Когда я печатаю размер класса в приложении и внутри одной из функций класса (которая вызывается, когда приложение вызывает ее) - я замечаю изменение размера.

Я использую VS 2010, и приложение печатает размер класса как 6304, а функция печатает это как 6352. Я скомпилировал как exe, так и dll в режиме Release | Win32. Оба имеют WIN32 и _WINDOWS. Но не определено WIN64.

Что я заметил больше, так это когда я печатаю sizeof(time_t) в exe, он печатает 4, а функция печатает в dll 8. Думаю, это может быть проблемой.

Есть идеи, где мне проверить?

Ответы [ 3 ]

7 голосов
/ 17 января 2012

Я согласен, что, скорее всего, возникнет проблема, если DLL и EXE не согласятся с расположением типов данных .

Однако я не вижу другого объяснения, кроме того, что вы должны использовать разные настройки проекта между двумя проектами.

Чтобы найти виновного, пометьте оба проекта в решении ( Ctrl + щелчок левой кнопкой мыши), затем откройте диалоговое окно свойств. Теперь в диалоговом окне отображаются только свойства , которые совпадают для обоих проектов в выбранной конфигурации. Несмотря на то, что диалог на первый взгляд кажется модальным, вы можете щелкнуть по одному из проектов, чтобы увидеть только его свойства, а также снова пометить оба из них, чтобы вы могли переключиться назад и вперед между этими взглядами . До сих пор я обычно находил проблему, используя эту технику.

Если это не удается, вы всегда можете сравнить файлы проекта . Они, будучи довольно болтливыми XML-файлами, делают это еще сложнее.

2 голосов
/ 17 января 2012

В VS 2010 тип time_t должен быть 64-разрядным (независимо от того, является ли цель построения 32-разрядной или 64-разрядной).Это можно переопределить для 32-разрядных целевых сборок, определив _USE_32BIT_TIME_T - так что вы должны убедиться, что это не определено в вашей сборке приложения (или, если это нужно определить там, вам также нужно определить это длявашей DLL или используйте тип __time32_t в определении класса DLL).

Я бы также удостоверился, что у вас не установлены разные параметры упаковки для DLL и сборок приложения (обратите внимание, что упаковкаКонфигурация может быть изменена в плохо написанных заголовочных файлах).Найдите параметр компилятора /Zp в журналах сборки и / или строки #pragma pack в заголовочных файлах без соответствующего #pragma pack(), который сбрасывается до значения по умолчанию.

2 голосов
/ 17 января 2012

Проблема выравнивания ?

Мне уже приходилось иметь дело с такими разными размерами одного и того же класса.

В лучшем случае это приводит к сбоям (поскольку ваш код будет пытаться читать / писать за пределами фактических данных класса), а в худшем - к странным ошибкам (например, установка значения переменной-члена равной 42 и при чтении это чтобы увидеть значение вместо 1376256 или что-то в этом роде.

Причина обычно была связана с проблемами выравнивания.

вот что вы можете сделать, чтобы убедиться, что ваша проблема связана с выравниванием:

Прямо перед (или после) определения класса добавьте следующую строку:

#pragma pack(show)

В выводе компиляции вы должны увидеть что-то вроде:

1>. \ Test_align.cpp (59): предупреждение C4810: значение пакета прагмы (показать) == 8

Это покажет выравнивание, когда ваш заголовок скомпилирован. Это будет появляться каждый раз, когда заголовок включен в файл CPP. Это значение должно всегда быть одинаковым как при компиляции DLL, так и при компиляции EXE.

Если они отличаются, хотя бы один раз, тогда у вас проблема с неправильным выравниванием ...

Выравнивание структуры по умолчанию для проекта?

Возможно, ваша DLL имеет выравнивание структуры по умолчанию, равное 1, в то время как у EXE есть другое значение. Пожалуйста, проверьте оба свойства проекта: Раздел "C / C ++", подраздел "Генерация кода", свойство "Выравнивание элементов структуры".

Чтобы все работало правильно, оба проекта должны иметь одинаковые значения.

Если EXE и DLL имеют разные значения, вы должны исправить это (обычно значение «по умолчанию» является хорошим: выберите «наследовать от родительского или проектного значения»).

Pragma pack?

Есть еще один способ нарушить выравнивание, то есть с помощью операторов #pragma pack. Например:

#pragma pack(show) // this will show the default value, i.e. 8 on my project

struct Data8       // the sizeof this struct is 8 bytes
{
   bool     m_bValue ;
   int      m_iValue ;
} ;

#pragma pack(push, 1)

#pragma pack(show) // this will show the now current value, i.e. 1

struct Data1       // the sizeof this struct is 5 bytes, thanks to the packing
{
   bool     m_bValue ;
   int      m_iValue ;
} ;

#pragma pack(pop)

#pragma pack(show) // this will show again the default value, i.e. 8

Итак, найдите операторы #pragma pack и убедитесь, что они всегда правильно установлены и не установлены (если вы нажимаете без всплывающих окон, то, вероятно, у вас есть ошибка).

Класс имеет одинаковое выравнивание в обоих проектах?

Если вы не нашли проблему в своем классе, возможно, проблема в одном из классов / структур, от которых она наследуется или имеет переменную-член.

Так что проверяйте их так же, как вы проверяли основной класс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...