Re[10]: Снова конструкторы и POD-типы
От: Cyberax Марс  
Дата: 27.07.05 13:40
Оценка:
dad wrote:

> MS>Как? Здесь будет *мгновенная автобусная ошибка*.

> ?

Bus error (passangers dumped)

На нормальных системах (SPARCах, I64 и т.п.) переменная должна быть
выравнена по своему размеру. То есть 8 байтный double должен быть
выравнен по границе 8 байт, 4-байтный int по границе 4 байт и т.п.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[12]: Снова конструкторы и POD-типы
От: Cyberax Марс  
Дата: 27.07.05 13:41
Оценка:
dad wrote:

> MS>Такая операция в общем случае является криминалом. Но на Intel —

> работает.
> "автобусная" ошибка регламентируется стандартом?

Да. В Стандарте есть пункты о выравнивании переменных, где упоминается о
UB в случаях неправильного выравнивания.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[17]: Снова конструкторы и POD-типы
От: Cyberax Марс  
Дата: 27.07.05 13:50
Оценка:
_Winnie wrote:

> Я и сложные типы типа std::vector, std::string *двигаю* по памяти при

> помощи memcpy... а это совсем не POD-типы.

Тут ведь как, по Стандарту такое делать нельзя, но на практике обычно
работает

Специально для поддержки быстрого move'а контейнеров я написал свою
STL-совместимую библиотеку. Например, возврат вектора из метода у меня
выглядит так:
typedef bcn::vector_builder<Obj> obj_vector_builder;
typedef bcn::fast_vector<Obj> obj_vector;

obj_vector method()
{
    obj_vector_builder b;
    b.insert(10,Obj(...));
    b.push_back(Obj());
    ...

    return b.yield();
}

При этом обычно происходит всего 1 динамическая аллокация (у меня
используется _grow для увеличения размера блока).

В результате с коллекциями стало работать намного приятнее.

> Говорят, возможно в будущем С++ стандарте будет какая-то специальная

> move-семантика. Но зачем усложнять язык, если это и сейчас возможно
> при помощи memcpy.

HINT: А если в объекте есть указатели на самого себя? Или если this
используется как ключ в какой-нибудь карте?

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[16]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 27.07.05 15:37
Оценка:
Здравствуйте, 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
Я жертва цепи несчастных случайностей. Как и все мы.
Re[17]: Снова конструкторы и POD-типы
От: Cyberax Марс  
Дата: 27.07.05 15:39
Оценка:
McSeem2 wrote:

> ME>Я читал, что когда данные в кэш линейке, выранивание на скорость

> доступа на ia32 не оказывает никакого влияния. Сам не проверял.
> Я тоже слышал такую версию. Но с другой стороны, я так же слышал, что
> для MMX/SSE операций выравнивание очень существенно влияет на
> производительность (причем, выравнивание на 64 или 128 бит).

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

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[17]: Снова конструкторы и POD-типы
От: Centaur Россия  
Дата: 27.07.05 18:22
Оценка: +1
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 дырки. Но вооще-то, можно отсортировать по убыванию размера, и тогда будет только небольшое пустое место в конце. Но что-то предполагать заранее нельзя.
Re[17]: Снова конструкторы и POD-типы
От: MaximE Великобритания  
Дата: 27.07.05 18:52
Оценка:
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).

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[18]: Снова конструкторы и POD-типы
От: dad  
Дата: 27.07.05 19:21
Оценка:
ME>Это максимальное выравнивание члена стр-ры. Выравнивание встроенных типов есть их размер.

>>
>> struct v
>> {
>>     char a;
>>     int  b;
>>     char c;
>>     int  d;
>>     char e;
>>     int  f;
>>     char g;
>>     int  h;
>> };
>>

>>
>> Здесь все зависит от того, упорядочиват ли компилятор данные в структуре.

Ну тут понятно, но непонятно где криминал в примере МакСима вот тут:

char a[5] = {0}; 
int i = *(int*)(a + 1);


что тут по чему выровнено? мы знаем что char это 1 байт, массив всегда располагается последовательно.
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Re[19]: Снова конструкторы и POD-типы
От: Cyberax Марс  
Дата: 27.07.05 19:32
Оценка:
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)];
    };


Теперь, например, мы можем делать так:
cow_storage_element *data=allocate(...);
new(&(data->counter_[0])) boost::detail::atomic_count(1);
...
new(&(data[1].data_[0])) value_type(...);


--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[20]: Снова конструкторы и POD-типы
От: dad  
Дата: 27.07.05 19:46
Оценка:
C>Предположим, что массив "a" начинается с адреса 4. Тогда a+1==5, попытка
C>разыменовать такой указатель на int вызовет автобусную ошибку.

Почему он вызовает ошибку то?
Мы точно знаем по адресу 5 лежит 1 байт, а 6, 7 и 8 еще три
другое дело, когда мы не значем что лежит там
как в случае с
struct {
char a[2];
int b;
};

(int*)(a + 1) -> тут понятно..
Или предполагается, что даже элементы массива типа char
могут быть выровнены на границу слова, например, без всякого нашего ведома?


C>Правильно надо писать примерно так (опять код из моей библиотеки ):


Блин я такое даже прочитать не могу
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Re[21]: Снова конструкторы и POD-типы
От: Cyberax Марс  
Дата: 27.07.05 20:01
Оценка:
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.


Либо еще можно делать так:
union
{
    char a[5];
    int i;
};



--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[20]: Снова конструкторы и POD-типы
От: MaximE Великобритания  
Дата: 27.07.05 20:03
Оценка: +1
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 вызовет автобусную ошибку. Правильно
> надо писать примерно так (опять код из моей библиотеки ):

[]

За шаблонами кода не видно. Чем не устраивает рабоче-крестьянский:

int main()
{
     size_t const align = 0x1000;
     size_t const buf_size = 8;

     char buf[buf_size + align - 1];
     char* aligned_buf = buf + align - 1 - (((uint_ptr_t)buf + align - 1) % align);

     printf("%x %x\n", buf, aligned_buf);
}


--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[21]: Снова конструкторы и POD-типы
От: McSeem2 США http://www.antigrain.com
Дата: 28.07.05 14:09
Оценка: 4 (1)
Здравствуйте, 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
Я жертва цепи несчастных случайностей. Как и все мы.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.