Почему структуры, хранящие простые указатели на внутреннюю память, не могут храниться в контейнерах stxxl?


В stxxl FAQ я нашел следующее:

Параметризация контейнеров STXXL

Типы контейнеров STXXL, такие как stxxl:: vector, могут быть параметризованы только с типом значения, который является POD (то есть без виртуальных функций, нет пользовательское назначение копии / деструктор и т. д.) и не содержит ссылки (включая указатели) на внутреннюю память. Как правило, " сложный" типы данных не удовлетворяют этим требованиям.

Вот почему stxxl::vector<std::vector<T> > и stxxl::vector<stxxl::vector<T> > являются недействительными. При необходимости используйте std::vector<stxxl::vector<T> >, или эмулировать двумерный массив с помощью делаем расчет индекса.

Невозможность использовать stxxl::vector<std::vector<T> > имеет смысл, поскольку контейнеры stxxl не вызывают конструкторы или деструкторы содержащихся элементов при изменении размера контейнера. Но как насчет хранения структуры, подобной этой:

struct S {
    int* a;
}

Если я гарантирую, что объект, на который указывает a, действителен до тех пор, пока существует экземпляр stxxl::vector<S>, то в чем проблема хранения этого struct в stxxl::vector<S>? Если конкретный экземпляр S должен быть перемещен на диск, то значение указателя a записывается на диск. Позже значение указателя будет восстановлено, и я смогу его использовать. Очевидно, что значение указателя зависит от машины и экземпляра, но является ли это вопросом , даже если я забочусь о времени жизни указанного объекта? Я не отправляю сериализованный объект через сокет и не сохраняю сериализованный объект в базе данных для последующего использования.

Есть Ли Я чего-то не хватает?

EDIT: кто-то напомнил мне, что stxxl не копирует указатель, и поэтому я могу получить указатель на мусор, когда я получу экземпляр struct S позже. Я знаю, что. Я гарантирую, что этот пункт действителен в течение всего срока действия программы.

3 2

3 ответа:

(включая указатели) на внутреннюю память

Это означает указатель на элемент структуры, или иначе указатель в память, которой управляет контейнер. Например, у вас есть

struct Foo {
     int *a;
     int b;
};

Foo f;
f.a = &f.b

Поскольку f.a теперь указывает на член структуры, и эта структура может быть скопирована, указатель может быть недействительным. Аналогично, если указатель указывает на любую другую структуру Foo, управляемую контейнером, который также можно перемещать.

Если у вас просто есть указатель, и Управляй тем, на что он указывает, у тебя все будет хорошо.

В реализациях сстрогой безопасностью указателя тот факт, что вы сохранили указатель на диск, недостаточен. Если этот указатель больше не находится в памяти, объект, на который он указывает, больше не действителен - даже если вы восстановите биты указателя с диска. В частности, это мог быть мусор, собранный без запуска dtor.

Я думаю, это потому, что данные в контейнерах копируются с использованием подхода типа memcpy - так что если бы у вас был указатель внутри класса, который вы хранили, вы бы копировали указатель, а не данные, на которые указывали.

Когда вы сериализуете такую структуру, указываемые данные не будут сериализованы, только указатель. Когда вы восстановите данные, у вас будет указатель, который указывает на мусор.