2010-12-12 3 views
12

Передача выровненных типов или структур с выровненными типами по значению не работает с некоторыми реализациями. Это разбивает контейнеры STL, потому что некоторые из методов (например, изменение размера) принимают свои аргументы по значению.Выравнивание типов и передача аргументов по значению

Я запускаю некоторые тесты с Visual Studio 2008 и не совсем уверен, когда и как проходит пропуск по значению. Моей главной задачей является функция foo. Кажется, он работает нормально, но может ли это быть результатом инкрустации или какого-то другого совпадения? Что, если я изменю свою подпись на void foo (const __m128 &)?

Ваш ввод очень приветствуется. Спасибо.

struct A 
{ 
    __m128 x; 
    int n; 
}; 

void foo(__m128); 
void bar(A); 

void f1() 
{ 
    // won't compile 
    // std::vector<A> vec1(3); 

    // compiles, but fails at runtime when elements are accessed 
    std::vector<__m128> vec2(3); 

    // this seems to work. WHY??? 
    std::vector<__m128, some_16_byte_aligned_allocator<__m128> > vec3(3); 

    __m128 x; 
    A a; 

    // passed by value, is it OK? 
    foo(x); 

    // won't compile 
    //bar(a); 
} 

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

Найден эта ссылка pass __m128 by value

+0

Каковы ошибки или предупреждения компиляции, которые вы получаете? Я предполагаю, что что-то вроде «формальный параметр ... не будет выровнен»? – celion

+0

Это то, что я получаю. ошибка C2719: 'unnamed-parameter': формальный параметр с __declspec (align ('16 ')) не будет выровнен – watson1180

+0

В x64 аргументы функции поддерживают выравнивание по 16 байт, поэтому эта проблема исчезает. Я знаю, что это не решает вашу непосредственную проблему, но эй, это немного лучше, чем ничего. ;) – jalf

ответ

2

Я думаю, единственный безопасный способ сделать это вообще пройти по ссылке. Некоторые платформы (например, Xbox 360) поддерживают передачу векторных аргументов в регистрах, но я не думаю, что это возможно на x86.

Для корпуса std::vector вам необходимо убедиться, что выделенная память выровнена до 16 байт; в противном случае вы столкнетесь с сбоями при попытке выполнить большинство операций с невыровненными векторами.

Если вы поддерживаете несколько платформ, безопасный план заключается в использовании typedef, например.

typedef const MyVector& MyVectorParameter; 

Затем вы можете изменить typedef на платформах, поддерживающих векторный проход по значению.

+0

Замена ассистента с помощью std :: vector <__m128>, но std :: vector все еще не компилируется. – watson1180

+0

Вы проверили 'sizeof (A)'? Если он не кратен 16 байтам, последующие элементы массива-хранилища, выделенные вектором, не будут выровнены, даже если начало хранения будет выровнено. –

+0

На моей платформе размер A равен 32 байтам.Неправильное выравнивание приведет к сбою во время выполнения, но вектор не будет компилироваться вне зависимости от распределителя. – watson1180

1

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