dad wrote:
> MS>Как? Здесь будет *мгновенная автобусная ошибка*. > ?
Bus error (passangers dumped)
На нормальных системах (SPARCах, I64 и т.п.) переменная должна быть
выравнена по своему размеру. То есть 8 байтный double должен быть
выравнен по границе 8 байт, 4-байтный int по границе 4 байт и т.п.
_Winnie wrote:
> Я и сложные типы типа std::vector, std::string *двигаю* по памяти при > помощи memcpy... а это совсем не POD-типы.
Тут ведь как, по Стандарту такое делать нельзя, но на практике обычно
работает
Специально для поддержки быстрого move'а контейнеров я написал свою
STL-совместимую библиотеку. Например, возврат вектора из метода у меня
выглядит так:
При этом обычно происходит всего 1 динамическая аллокация (у меня
используется _grow для увеличения размера блока).
В результате с коллекциями стало работать намного приятнее.
> Говорят, возможно в будущем С++ стандарте будет какая-то специальная > move-семантика. Но зачем усложнять язык, если это и сейчас возможно > при помощи memcpy.
HINT: А если в объекте есть указатели на самого себя? Или если this
используется как ключ в какой-нибудь карте?
Здравствуйте, MaximE, Вы писали:
ME>Я читал, что когда данные в кэш линейке, выранивание на скорость доступа на ia32 не оказывает никакого влияния. Сам не проверял.
Я тоже слышал такую версию. Но с другой стороны, я так же слышал, что для MMX/SSE операций выравнивание очень существенно влияет на производительность (причем, выравнивание на 64 или 128 бит).
>> Именно поэтому в структурах появляюся "дыры" от выравнивания. И sizeof(struct) != sum(sizeof(data_members)) в общем случае.
ME>В-общем случае размер структуры кратен ее выравниванию. Это связано с тем, что в массивах между элементами не может быть "дыр", поэтому если размер структуры не был бы кратен выравниванию, массив из этих структур создать не было бы возможно.
А что такое "выравнивание структуры"? Выравнивание по максимальному элементу данных?
struct v
{
char a;
int b;
char c;
int d;
char e;
int f;
char g;
int h;
};
Здесь все зависит от того, упорядочиват ли компилятор данные в структуре. Если нет, то размер будет таков, как если бы мы все char заменили на int. И соответственно, 4 дырки. Но вооще-то, можно отсортировать по убыванию размера, и тогда будет только небольшое пустое место в конце. Но что-то предполагать заранее нельзя.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
McSeem2 wrote:
> ME>Я читал, что когда данные в кэш линейке, выранивание на скорость > доступа на ia32 не оказывает никакого влияния. Сам не проверял. > Я тоже слышал такую версию. Но с другой стороны, я так же слышал, что > для MMX/SSE операций выравнивание очень существенно влияет на > производительность (причем, выравнивание на 64 или 128 бит).
Насколько я помню, SSE не умеет работать с невыровненными данными.
MS>А что такое "выравнивание структуры"? Выравнивание по максимальному элементу данных? MS>
MS>struct v
MS>{
MS> char a;
MS> int b;
MS> char c;
MS> int d;
MS> char e;
MS> int f;
MS> char g;
MS> int h;
MS>};
MS>
MS>Здесь все зависит от того, упорядочиват ли компилятор данные в структуре.
Переупорядочивать — в данном случае не имеет права. Ибо 9.2/1:
Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object. The order of allocation of nonstatic data members separated by an access-specifier is unspecified (11.1). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).
MS> Если нет, то размер будет таков, как если бы мы все char заменили на int. И соответственно, 4 дырки. Но вооще-то, можно отсортировать по убыванию размера, и тогда будет только небольшое пустое место в конце. Но что-то предполагать заранее нельзя.
On Wed, 27 Jul 2005 19:37:35 +0400, McSeem2 <12737@users.rsdn.ru> wrote:
[]
> В-общем случае размер структуры кратен ее выравниванию. Это связано с тем, что в массивах между элементами не может быть "дыр", поэтому если размер структуры не был бы кратен выравниванию, массив из этих структур создать не было бы возможно. > > А что такое "выравнивание структуры"? Выравнивание по максимальному элементу данных?
Это максимальное выравнивание члена стр-ры. Выравнивание встроенных типов есть их размер.
>
> struct v
> {
> char a;
> int b;
> char c;
> int d;
> char e;
> int f;
> char g;
> int h;
> };
>
> > Здесь все зависит от того, упорядочиват ли компилятор данные в структуре.
В POD компилятор не может переупорядочивать члены.
> Если нет, то размер будет таков, как если бы мы все char заменили на int. И соответственно, 4 дырки. Но вооще-то, можно отсортировать по убыванию размера, и тогда будет только небольшое пустое место в конце. Но что-то предполагать заранее нельзя.
Максимальное выравнивание члена в этой стр-ре — sizeof(int). Поэтому sizeof(v) % sizeof(int) == 0 и alignof(v) == alignof(int).
dad wrote:
> Ну тут понятно, но непонятно где криминал в примере МакСима вот тут: > >char a[5] = {0}; >int i = *(int*)(a + 1); > > что тут по чему выровнено? мы знаем что char это 1 байт, массив всегда > располагается последовательно.
Предположим, что массив "a" начинается с адреса 4. Тогда a+1==5, попытка
разыменовать такой указатель на int вызовет автобусную ошибку. Правильно
надо писать примерно так (опять код из моей библиотеки ):
//This union is used to ensure that COW storage elements will be
properly aligned.
template<class AllocatorT> union cow_storage_element
{
typedef boost::detail::atomic_count counter_type;
typedef typename AllocatorT::value_type value_type;
typename boost::type_with_alignment<
(boost::alignment_of<counter_type>::value >
boost::alignment_of<value_type>::value)
? boost::alignment_of<counter_type>::value
: boost::alignment_of<value_type>::value
>::type a;
char counter_[sizeof(counter_type)];
char data_[sizeof(value_type)];
};
C>Предположим, что массив "a" начинается с адреса 4. Тогда a+1==5, попытка C>разыменовать такой указатель на int вызовет автобусную ошибку.
Почему он вызовает ошибку то?
Мы точно знаем по адресу 5 лежит 1 байт, а 6, 7 и 8 еще три
другое дело, когда мы не значем что лежит там
как в случае с
struct {
char a[2];
int b;
};
(int*)(a + 1) -> тут понятно..
Или предполагается, что даже элементы массива типа char
могут быть выровнены на границу слова, например, без всякого нашего ведома?
C>Правильно надо писать примерно так (опять код из моей библиотеки ):
Блин я такое даже прочитать не могу
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
dad wrote:
> C>Предположим, что массив "a" начинается с адреса 4. Тогда a+1==5, > попытка > C>разыменовать такой указатель на int вызовет автобусную ошибку. > Почему он вызовает ошибку то?
Массив "a" — это массив однобайтных символов (не требующих
выравнивания), компилятор имеет право разместить этот массив как угодно.
В том числе, может разместить по адресу, кратному 4. Следовательно
второй элемент массива (a+1) будет иметь адрес вида 4k+1.
> Мы точно знаем по адресу 5 лежит 1 байт, а 6, 7 и 8 еще три
Неважно что там лежит. Число 5 не делится на 4 (размер int'а), значит
произойдет _аппаратная_ ошибка выравнивания. Ну не может процессор с
такими данными работать.
> C>Правильно надо писать примерно так (опять код из моей библиотеки ): > Блин я такое даже прочитать не могу
Можно записать более просто:
#ifdef _WIN32
//Non-aligned types can be safely used on win32.template<class T> size_t alignment_of()
{
return 1;
}
#else//General fallback implementation.template<class T> size_t alignment_of()
{
return sizeof(T);
}
#endif
...
char a[5+(alignment_of(int)+1)/2]; //This array will have enough space for properly aligned int.
int i=*(int*)(a+a%alignment_of(int)); //Get properly aligned integer.
On Wed, 27 Jul 2005 23:32:21 +0400, Cyberax <37054@users.rsdn.ru> wrote:
> dad wrote: > >> Ну тут понятно, но непонятно где криминал в примере МакСима вот тут: >> >> char a[5] = {0}; >> int i = *(int*)(a + 1); >> >> что тут по чему выровнено? мы знаем что char это 1 байт, массив всегда >> располагается последовательно. > > Предположим, что массив "a" начинается с адреса 4. Тогда a+1==5, попытка > разыменовать такой указатель на int вызовет автобусную ошибку. Правильно > надо писать примерно так (опять код из моей библиотеки ):
[]
За шаблонами кода не видно. Чем не устраивает рабоче-крестьянский:
Здравствуйте, dad, Вы писали:
dad>Почему он вызовает ошибку то? dad>Мы точно знаем по адресу 5 лежит 1 байт, а 6, 7 и 8 еще три dad>другое дело, когда мы не значем что лежит там dad>как в случае с dad>struct { dad> char a[2]; dad> int b; dad>};
Неважно, что и как там лежит. Важно, что адрес нечетный.
mov eax,[esi]
На многих процессорах, аналог этой команды вызовет bus error, в случае, если текущее значение esi не кратно 4.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.