Нечетность выделения памяти классам потоков на встроенной платформе - PullRequest
6 голосов
/ 03 августа 2010

Я столкнулся со странной проблемой, которую мне удалось отследить, но я до сих пор не вижу причины. Может быть, кто-то здесь может пролить свет?

Я использую процессор PowerPC поверх VxWorks 5.5, разрабатываемого на C ++ с помощью цепочки инструментов PPCgnu604.

У меня есть такой класс:

class MyClass
{
  public:
    void run( void );
  private:
    CommandMesssageClass command;
    StatusMessageClass status;
};

Когда мое приложение запускается, оно динамически выделяет экземпляр MyClass и порождает поток, указывающий на его функцию «run». По сути, он просто сидит там, опрашивая команды, и после получения выдаст статус обратно.

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

Проблема, которую я вижу, состоит в том, что, когда и команда, и сообщения о состоянии определены как закрытые члены класса, я получу изменение в доступных байтах в памяти, несмотря на то, что не должно быть динамического выделения памяти. Это важно, потому что это происходит в процессе, который должен быть детерминированным и безопасным для скорости.

Если я переместлю одно или оба объявления сообщений в функцию run, она будет работать нормально без дополнительного выделения!

Мне, должно быть, не хватает чего-то фундаментального в моем понимании объявлений C ++ и распределения памяти. Насколько я понимаю, экземпляр класса, который я динамически создаю, будет полностью размещен в куче (включая все переменные-члены) при его создании. Различие, которое я вижу здесь, состоит в том, что перемещение объявлений сообщений в функцию run помещает их в стек. Куча в этом случае более чем достаточно велика, чтобы соответствовать всему размеру класса. Почему кажется, что он не выделяет достаточно памяти, пока не будут использованы определенные части?

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

Для отслеживания распределения памяти я использую следующий вызов memxib (или memPartLib) из VxWorks:

memPartInfoGet( memSysPartId, &partitionStatus );
...
bytesFree = partitionStatus.numBytesFree;

Edit:

Для пояснения, объект MyClass создается и инициализируется в процедуре инициализации, а затем код входит в безопасную для скорости обработку. В течение этого времени после получения командного сообщения по последовательной линии (первое взаимодействие с объектами сообщения «Команда» или «Состояние») выделяется дополнительная память (или, точнее, уменьшается количество свободных байтов). Это плохо, потому что динамическое распределение памяти не является детерминированным.

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

1 Ответ

2 голосов
/ 18 августа 2010

Я, должно быть, упускаю что-то фундаментальное из моего понимания объявлений C ++ и распределения памяти.

Я так не думаю.Все, что вы говорите, что вы ожидаете выше, правильно: программисты игр все время полагаются на это поведение.: -)

Почему кажется, что он не выделяет достаточно памяти, пока не используются определенные порции?

Для краткости вы опустили кишки класса.У меня был некоторый опыт отладки подобных проблем, и я думаю, что где-то там библиотечная функция , по сути, , выполняет распределение во время выполнения, о котором вы не знаете.

Другими словами, распределение времени выполнения есть в обоих случаях, но два разных размера MyClass означают, что пулы malloc заполняются по-разному.Вы можете доказать это, переместив объекты в стек внутри run (), но добавив MyClass к тому же размеру.Если вы по-прежнему видите свободное падение mem, то это не имеет никакого отношения к тому, находятся ли эти объекты в куче или в стеке ... это вторичный эффект, который происходит из-за размера MyClass.

Помните,malloc является коренастым - большинство реализаций не выполняют однозначное распределение для каждого вызова malloc.Вместо этого он перераспределяет и удерживает память в пуле и при необходимости увеличивает эти пулы.

Я не знаком с вашей цепочкой инструментов, но типичные подозрения на неожиданные небольшие выделения во встроенных системах включают функции ctype (локали) и функции даты / времени (часовой пояс).

...