Данные не правильно выровнены в Visual Studio при запуске в отладчике - PullRequest
1 голос
/ 08 марта 2011

Я уже некоторое время работаю с SSE и вижу свою долю проблем с выравниванием. Это, однако, за пределами моего понимания:

получаю ли я другое выравнивание запустить программу с помощью F5 (отладка) или запускаю ли я его вне отладчика (Ctrl + F5)!

Некоторая справочная информация: Я использую оболочку для типа данных с поддержкой SSE - с перегруженными операторами и пользовательским распределителем (перегруженные операторы new и delete используют _mm_malloc и _mm_free). Но в приведенном ниже примере мне удалось еще больше уменьшить проблему, то есть проблема также возникает, даже если я не использую пользовательский распределитель.

Как вы можете видеть ниже, в main () я динамически размещаю объект TestClass в куче, которая содержит объект типа SSEVector. Я использую фиктивную float[2] переменную-член для "неправильного выравнивания" стека.

Я получаю следующий вывод при запуске с F5:

object address 00346678
_memberVariable1 address 00346678
_sseVector address 00346688

И если я бегу с Ctrl + F5:

object address 00345B70
_memberVariable1 address 00345B70
_sseVector address 00345B80

Как видите, выравнивание отличается (т.е. не 16-байтовым), когда я запускаю его в отладчике. Это просто совпадение, что выравнивание является правильным при использовании Ctrl-F5? Я использую Visual Studio 2010 с новым проектом (настройки по умолчанию).

Если я объявлю объект в стеке, т.е. TestClass myObject;, эта проблема не появится. Использование __declspec(align(16)) также не помогает.

Код, который я использовал для воспроизведения проблемы:

#include <iostream>
#include <string>
#include <xmmintrin.h>  // SSE
//#include "DynAlignedAllocator.h"

//////////////////////////////////////////////////////////////
class SSEVector /*: public DynAlignedAllocator<16>*/
{
public:
    SSEVector() { }

    __m128 vec;
};

class TestClass
{
public:
    TestClass() { }

    /*__declspec(align(16))*/ float _memberVariable1 [2];
    SSEVector _sseVector;
};

//////////////////////////////////////////////////////////////
int main (void)
{
    TestClass* myObject = new TestClass;

    std::cout << "object address " << myObject << std::endl;
    std::cout << "_memberVariable1 address " << &(myObject->_memberVariable1) << std::endl;
    std::cout << "_sseVector address " << &(myObject->_sseVector) << std::endl;

    delete myObject;

    // wait for ENTER
    std::string dummy;
    std::getline(std::cin, dummy);

    return 0;
}

Любые подсказки или комментарии приветствуются. Заранее спасибо.

1 Ответ

5 голосов
/ 08 марта 2011

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

Установите _NO_DEBUG_HEAP=1 в настройках своего окружения и посмотрите, поможет ли это.

См. Например http://msdn.microsoft.com/en-us/library/aa366705%28v=vs.85%29.aspx

Однако выравнивание не гарантируется при выделении с помощью malloc или new. «Правильный» способ решения этой проблемы в VS - использовать _aligned_malloc.

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

См. Как работает выравнивание с упаковкой данных

Что происходит в ваших случаях (кроме, казалось бы, случайной разницы между отладчиком и не отладчиком):

SSEVector объявляется невыровненным. Если вы выделите его напрямую, используя _aligned_malloc, он будет выровнен. TestClass также не выровнен и использует упаковку по умолчанию. Если вы выделите его с помощью _aligned_malloc, экземпляр TestClass будет правильно выровнен. Это вам совсем не поможет, поскольку вы хотите, чтобы переменная-член SSEVector была выровнена.

Добавление требования выравнивания для SSEVector с использованием __declspec(align) сообщит компилятору, что SSEVector переменные стека должны быть выровнены, и , что SSEVector как член структуры должен быть выровнен в структуре / классе . Теперь, если вы выделите TestClass, используя _aligned_malloc, он будет правильно выровнен. И смещение SSEVector в структуре также правильно выровнено из-за declspec, поэтому абсолютный адрес SSEVector будет правильным для вашего использования.

...