LINUX.ORG.RU

C++ - ошибка при выполнении оператора размещения


0

0

Столкнулся с проблемой, которая совершенно сбила меня с толку - до сих пор сталкиваться с подобным не приходилось. Значит, есть библиотека, которая используется в отдельном cli-приложении и в apache-вском модуле. Библиотека нормально обложена тестами, да в cli-приложении ведёт себе совершенно адекватно, но вот в апачевском модуле... Есть такой проблемный код: struct tander::REST::catalog::pimpl { typedef std::map<std::string, boost::shared_ptr<catalog> > catalog_map_type; typedef std::map<std::string, boost::shared_ptr<conveyor> > http_method_conveoyr_map_type; typedef std::map<std::string, http_method_conveoyr_map_type> url_conveyor_map_type;

catalog_map_type catalog_map_; url_conveyor_map_type url_map_; http_method_conveoyr_map_type item_map_; }; Теперь, при после вызова конструктора pimpl, обращение к item_map_ ведёт к падению процесса apache с сообщением "Segmentation fault". Добавление виртуального деструктора к pimpl ведёт к тому, что процесс падает при обращение к любой члену pimpl. Однако, если вместо непосредственного вызова конструктор использовать такой вот код: pimpl_ = reinterpret_cast<pimpl*>(operator new(sizeof(pimpl))); new (&pimpl_->catalog_map_) pimpl::catalog_map_type; new (&pimpl_->url_map_) pimpl::url_conveyor_map_type; new (&pimpl_->item_map_) pimpl::http_method_conveoyr_map_type; То всё работает отлично. Дальнейшее иследование показало, что pimpl_ = reinterpret_cast<pimpl*>(operator new(sizeof(pimpl))); new (pimpl_) pimpl; не помогает. Необходима ручная инициализация членов структуры. Т.е. фактически можно достаточно смело утверждать, что дело в ошичной работе оператора размещения для данной структуры. Собственно, в чём дело и как победить?


Извиняюсь, за форматирование предудыщего сообщения - пишу на этом форуме впервые :-)

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

Значит, есть библиотека, которая используется в отдельном cli-приложении и в apache-вском модуле. Библиотека нормально обложена тестами, да в cli-приложении ведёт себе совершенно адекватно, но вот в апачевском модуле...

Есть такой проблемный код:
struct tander::REST::catalog::pimpl {
typedef std::map<std::string, boost::shared_ptr<catalog> > catalog_map_type;
typedef std::map<std::string, boost::shared_ptr<conveyor> > http_method_conveoyr_map_type;
typedef std::map<std::string, http_method_conveoyr_map_type> url_conveyor_map_type;

catalog_map_type catalog_map_;
url_conveyor_map_type url_map_;
http_method_conveoyr_map_type item_map_;
};

Теперь, при после вызова конструктора pimpl, обращение к item_map_ ведёт к падению процесса apache с сообщением "Segmentation fault". Добавление виртуального деструктора к pimpl ведёт к тому, что процесс падает при обращение к любой члену pimpl. Однако, если вместо непосредственного вызова конструктор использовать такой вот код:

pimpl_ = reinterpret_cast<pimpl*>(operator new(sizeof(pimpl)));
new (&pimpl_->catalog_map_) pimpl::catalog_map_type;
new (&pimpl_->url_map_) pimpl::url_conveyor_map_type;
new (&pimpl_->item_map_) pimpl::http_method_conveoyr_map_type;

То всё работает отлично. Дальнейшее иследование показало, что

pimpl_ = reinterpret_cast<pimpl*>(operator new(sizeof(pimpl)));
new (pimpl_) pimpl;

не помогает. Необходима ручная инициализация членов структуры. Т.е. фактически можно достаточно смело утверждать, что дело в ошичной работе оператора размещения для данной структуры.

Собственно, в чём дело и как победить?

xaka
() автор топика
Ответ на: комментарий от xaka

Забыл сказать о системе:
Gentoo Linux (регулярно обновляюсь)
gcc 4.2.0
apache 2.2.4
glibc-2.6.1

xaka
() автор топика
Ответ на: комментарий от xaka

Апач под valgrind-ом пустите, посмотрите, почему он падает, какие ошибки перед этим происходят. Если совсем загадочно - стоит попробовать скомпилировать gcc из другой ветки, может даже ошибка в компиляторе, хотя это весьма редкая ситуация.

Legioner ★★★★★
()
Ответ на: комментарий от zim

На всякий случай -- о том, что struct и class в С++ одно и тоже осведомлен

zim
()
Ответ на: комментарий от zim

> Если не ошибаюсь, operator new гарантирует вызов конструктора

operator new выделяет сырую память.

Во второй строке placement new, который вызывает конструктор

dilmah ★★★★★
()
Ответ на: комментарий от xaka

Мля, только одно объяление структуры не влезает в 70 символов по ширине и нечитабельно совершенно, боюсь даже представить как выглядит остальной код :)

Reset ★★★★★
()
Ответ на: комментарий от dilmah

>> Разве operator new гарантирует обнуление памяти?

> А placement new не требует чтобы память была обнулена.

Я знаю. Но в cli и Apache могут использоваться разные аллокаторы - то, что в cli, может обнулять, а тот, что в Apache - может не обнулять. Получим как раз описываемое различие в поведении.

tailgunner ★★★★★
()
Ответ на: комментарий от xaka

> Есть такой проблемный код:
[...]
> Однако, если вместо непосредственного вызова конструктор использовать
[...]

Что ты понимаешь под непосредственным вызовом конструктора в данном случае?
ISO/IEC 14882:1998(E)
5.3.4 New
15.
Не оно?

Если нет, то:
Какие(есть ли) ворнинги при капуляции? Какой уровень ворнингов? Какой капулятор?
Что происходит при добавлении конструктора pimpl::pimpl() {}?

gpg
()
Ответ на: комментарий от xaka

Вдогонку. Сразу не обратил внимания.
8<-------------------------------
pimpl_ = reinterpret_cast<pimpl*>(operator new(sizeof(pimpl)));
new (pimpl_) pimpl;

не помогает.
8<-------------------------------
Если ты и в изначальном коде опускал скобки, сто против одного, твоя проблема в их отсутствии.
Попробуй new (pimpl_) pimpl();
А лучше просто pimpl_ = new pimpl();

gpg
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.