McSeem2 wrote:
> Хорошо, раскрываю карты. Дело даже не в производительности. Как мне > при поможи std::copy() корректно "вытащить" данные из памяти, > находящиеся по невыровненному адресу? По-моему никак.
Данный конкретный случай в std::copy как раз работать будет.
C>В этом коде можно многое улучшить, но идея должна быть понятна.
Идея понятна, спасибо. Но чисто в качестве придирки — это уже полное безобразие (я не хочу наглеть до такой степени): Если объект является bitwise_moveable, то он по определению не может иметь нетривиальный деструктор (который что-то там реально уничтожает). Если же деструктор действительно что-то делает, сразу ставим жирный крест на побитовом копировании. Такое ограничение представляется мне вполне разумным, ибо опасно.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Ну что тут сказать В принципе, я с тобой согласен.
Ну а в желании "взять на себя риск нарушить этот запрет" ты далеко не одинок. По крайней мере я встречал это нарушение не так уж и редко
McSeem2 wrote:
> C>В этом коде можно многое улучшить, но идея должна быть понятна. > Идея понятна, спасибо. Но чисто в качестве придирки — это уже полное > безобразие (я не хочу наглеть до такой степени): Если объект является > bitwise_moveable, то он по определению не может иметь нетривиальный > деструктор (который что-то там реально уничтожает).
Не обязательно, у меня используются бит-копируемые объекты, в которых в
деструкторе делаются assert'ы и некоторые другие проверки. Так что пусть
живет.
> Если же деструктор действительно что-то делает, сразу ставим жирный > крест на побитовом копировании. Такое ограничение представляется мне > вполне разумным, ибо опасно.
У меня по умолчанию побитовое копирование будет работать только для
простых типов. Для более сложных нужно ставить флажок
ENABLE_BITWISE_MOVEABLE — если его явно поставить, то уж сам виноват....
McSeem2 wrote:
> C>Данный конкретный случай в std::copy как раз работать будет. > > // TEMPLATE FUNCTION copy >template<class _II, class _OI> inline > _OI copy(_II _F, _II _L, _OI _X) > {for (; _F != _L; ++_X, ++_F) > *_X = *_F; > return (_X); } > > Как? Здесь будет мгновенная автобусная ошибка.
Компилятор обнаружит, что размер структуры не позволяет срабатывать
выравниванию, и сгенерирует byte-by-byte копирование. А байты везде
читаются без выравнивания.
Здравствуйте, Cyberax, Вы писали:
C>Компилятор обнаружит, что размер структуры не позволяет срабатывать C>выравниванию, и сгенерирует byte-by-byte копирование. А байты везде C>читаются без выравнивания.
Не верю!
struct point { int x,y; };
char array[100];
point p[4];
std::copy((point*)(array+1), (point*)(array+1+sizeof(p)), p);
И что, на SGI не возникнет автобусной ошибки? Я ведь проверю! И очень скоро проверю!
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
#include <algorithm>
struct point { int x,y; };
void main()
{
char array[100];
point p[4];
std::copy((point*)(array+1), (point*)(array+1+sizeof(p)), p);
}
rndusexwally:~>CC buserror.cpp
cc-3563 CC: WARNING File = buserror.cpp, Line = 5
return type of function "main" must be "int"
void main()
^
rndusexwally:~>./a.out
Bus error (core dumped)
rndusexwally:~>
Как и ожидалось... Интересно, откуда компилятор может заранее знать, что указатель не выровнен? Это возможно только в run-time, что есть накладно весьма.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, dad, Вы писали:
dad>"автобусная" ошибка регламентируется стандартом? dad>Внешне криминала не видно, получаешь 4 байта [1-4]
Это регламентируется не стандартом C++, а архитектурой процессоров. Если процессор не позволяет так копировать, а некий (абстрактный) язык позволяет, то bus error в run-time будет в любом языке. А стандарт не имеет права запрещать подобный криминал (да и не может по жизни). То есть, это все — на совести программиста.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
dad>>"автобусная" ошибка регламентируется стандартом? dad>>Внешне криминала не видно, получаешь 4 байта [1-4]
MS>Это регламентируется не стандартом C++, а архитектурой процессоров. Если процессор не позволяет так копировать, а некий (абстрактный) язык позволяет, то bus error в run-time будет в любом языке. А стандарт не имеет права запрещать подобный криминал (да и не может по жизни). То есть, это все — на совести программиста.
А на какой платформе такое у тебя? С чем это связано чисто технически.
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Здравствуйте, dad, Вы писали:
dad>А на какой платформе такое у тебя? С чем это связано чисто технически.
На SGI, на Sun Ultra Sparc, на HP, на DEC Alpha и многих других. Ну не культурно это обращаться к памяти как к int, если адрес не выровнен на int. На Intel, кстати тоже. Это хоть и работает технически, но значительно медленнее, чем в случае выровненных данных. Именно поэтому в структурах появляюся "дыры" от выравнивания. И sizeof(struct) != sum(sizeof(data_members)) в общем случае.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
McSeem2 wrote:
> На SGI, на Sun Ultra Sparc, на HP, на DEC Alpha и многих других. Ну не культурно это обращаться к памяти как к int, если адрес не выровнен на int. На Intel, кстати тоже. Это хоть и работает технически, но значительно медленнее, чем в случае выровненных данных.
Я читал, что когда данные в кэш линейке, выранивание на скорость доступа на ia32 не оказывает никакого влияния. Сам не проверял.
> Именно поэтому в структурах появляюся "дыры" от выравнивания. И sizeof(struct) != sum(sizeof(data_members)) в общем случае.
В-общем случае размер структуры кратен ее выравниванию. Это связано с тем, что в массивах между элементами не может быть "дыр", поэтому если размер структуры не был бы кратен выравниванию, массив из этих структур создать не было бы возможно.
Я и сложные типы типа std::vector, std::string двигаю по памяти при помощи memcpy... а это совсем не POD-типы. Говорят, возможно в будущем С++ стандарте будет какая-то специальная move-семантика. Но зачем усложнять язык, если это и сейчас возможно при помощи memcpy.
Правильно работающая программа — просто частный случай Undefined Behavior
McSeem2 wrote:
> Не верю! > > struct point { int x,y; }; > char array[100]; > point p[4]; > std::copy((point*)(array+1), (point*)(array+1+sizeof(p)), p); > > И что, на SGI не возникнет автобусной ошибки? Я ведь проверю! И очень > скоро проверю!
Так вот будет:
struct point { int x,y; };
char *array=(char*)malloc(100)
point p[4];
std::copy(&p[0], &p[0]+4, array);