Всем привет!
Я с asio и boost только начинаю работать и вот наткнулся на проблему.
Суть ее в том, что вываливается исключение при работе с boost::asio::placeholders.
Например, я делаю следующий вызов async_accept:
pacceptor_->async_accept(pclient->GetSocket(),
boost::bind(&CNetCopyServer::OnAccept, this, pclient,
boost::asio::placeholders::error));
Возникает исключение
Unhandled exception at 0x0053ae4e in MDBCopySrv.exe: 0xC0000005: Access violation reading location 0x00000000.
Посмотрев в дисассемблере, увидел что исключение получается на строчке:
EAX = 0 и следовательно получаем исключение. Но из-за чего такое происходит?
Что я не так сделал, ведь вроде бы по туториалу пытался сделать..?
Заранее спасибо за помощь
Здравствуйте, savitar, Вы писали:
S>Ничего криминального в указанном месте нет. Видимо где-то память хериться.
Как оказалось дело было в следующем.
В самом начале запуска программы происходит инициализация глобальных переменных,
в том числе и boost::asio::placeholders::error
После этого вывоза она инициализируется, все хорошо.. &error показывает валидный адрес
Эта инициализация вызывается три раза. Причем между ними &error показывает 0.
Моя программа — это сервис windows, и я делаю ее с помощью ATL, где
есть класс CAtlServiceModuleT, который помогает в создании сервиса и управлении им.
Создание внутренних объектов происходит прямо в конструкторе моего унаследованного класса.
CMDBCopySrvModule() : CAtlServiceModuleT()
{
m_pCopyManager = new CCopyManager();
m_pNetServer = new CNetCopyServer(m_pCopyManager);
m_pNetServer->StartServer();
}
Объект этого класса тоже является глобальной переменной и ее создание происходит вместе с placeholders::error.
Причем она вклинивается между теми тремя инициализациями placeholders::error.
И получается что уже в конструкторе моего класса &error = 0.
(На момент входа в этот конструктор &error еще валидный. Но дальше происходит нечто странное.
Как только я захожу в конструктор CCopyManager, &error становиться равен 0.)
Проблема решилась переносом создания внутренних объектов в метод RunMessageLoop.
Получается что нельзя пользоваться asio в конструкторе глобальных объектов, так как некоторые его объекты еще не до конца созданы.
Но я по-прежнему не понимаю где &error успевает обнуляться между этими вызовами и почему их три?
CRT каким-то хитрым способом строит список инициализации или что?
Здравствуйте, fk, Вы писали:
fk>Получается что нельзя пользоваться asio в конструкторе глобальных объектов, так как некоторые его объекты еще не до конца созданы.
в asio какое-то порно с глобальными переменными. в курсе, что WSAStartup вызывается так же и чем это грозит?
fk>CRT каким-то хитрым способом строит список инициализации или что?
у vc++ можно ведь самому установить порядок инициализации глобальных переменных, вот только не помню директиву.
Здравствуйте, о_О, Вы писали:
о_О>Здравствуйте, fk, Вы писали:
fk>>Получается что нельзя пользоваться asio в конструкторе глобальных объектов, так как некоторые его объекты еще не до конца созданы. о_О>в asio какое-то порно с глобальными переменными.
Глобальные переменные — это как езда по разделительной полосе. Всё ОК, пока не ещё одного такого же не встретишь.
Здравствуйте, о_О, Вы писали:
fk>>Получается что нельзя пользоваться asio в конструкторе глобальных объектов, так как некоторые его объекты еще не до конца созданы. о_О>в asio какое-то порно с глобальными переменными. в курсе, что WSAStartup вызывается так же и чем это грозит?
Здравствуйте, jazzer, Вы писали:
fk>>>Получается что нельзя пользоваться asio в конструкторе глобальных объектов, так как некоторые его объекты еще не до конца созданы. о_О>>в asio какое-то порно с глобальными переменными. в курсе, что WSAStartup вызывается так же и чем это грозит?
J>багрепорт уже отправили им?
Здравствуйте, Mazay, Вы писали:
M>Здравствуйте, jazzer, Вы писали:
fk>>>>Получается что нельзя пользоваться asio в конструкторе глобальных объектов, так как некоторые его объекты еще не до конца созданы. о_О>>>в asio какое-то порно с глобальными переменными. в курсе, что WSAStartup вызывается так же и чем это грозит?
J>>багрепорт уже отправили им?
M>Какой смысл? Всё равно нормального решения нет.
Ну О_о, видимо, решение знает, раз так резко высказывается...
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, о_О, Вы писали:
fk>>>Получается что нельзя пользоваться asio в конструкторе глобальных объектов, так как некоторые его объекты еще не до конца созданы. о_О>>в asio какое-то порно с глобальными переменными. в курсе, что WSAStartup вызывается так же и чем это грозит?
J>багрепорт уже отправили им?
зачем? что я ему скажу? "эй, линуксоид, кто ж WSAStartup на глобальную переменную вешает?"
Здравствуйте, о_О, Вы писали:
о_О>>>в asio какое-то порно с глобальными переменными. в курсе, что WSAStartup вызывается так же и чем это грозит? J>>багрепорт уже отправили им? о_О>зачем? что я ему скажу? "эй, линуксоид, кто ж WSAStartup на глобальную переменную вешает?"
если уберешь "линуксоид" и приведешь вместо этого цитату из MSDN, а еще лучше, пример падающей программы — то да.
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, о_О, Вы писали:
о_О>>>>в asio какое-то порно с глобальными переменными. в курсе, что WSAStartup вызывается так же и чем это грозит? J>>>багрепорт уже отправили им? о_О>>зачем? что я ему скажу? "эй, линуксоид, кто ж WSAStartup на глобальную переменную вешает?"
J>если уберешь "линуксоид" и приведешь вместо этого цитату из MSDN, а еще лучше, пример падающей программы — то да.
нуу... эту проблему можно решить путем добавления флага компиляции ASIO_MANUAL_INITIALIZATION, но...
Здравствуйте, о_О, Вы писали:
о_О>Здравствуйте, jazzer, Вы писали:
J>>Здравствуйте, о_О, Вы писали:
о_О>>>>>в asio какое-то порно с глобальными переменными. в курсе, что WSAStartup вызывается так же и чем это грозит? J>>>>багрепорт уже отправили им? о_О>>>зачем? что я ему скажу? "эй, линуксоид, кто ж WSAStartup на глобальную переменную вешает?"
J>>если уберешь "линуксоид" и приведешь вместо этого цитату из MSDN, а еще лучше, пример падающей программы — то да.
о_О>нуу... эту проблему можно решить путем добавления флага компиляции ASIO_MANUAL_INITIALIZATION, но...
о_О>*тут было очень много разоблачающего текста*
Здравствуйте, jazzer, Вы писали:
J>Давай ты это все изложишь на английском и трекере буста, а сюда ссылку? J>Я тебе даже помогу: J>https://svn.boost.org/trac/boost/newticket
Давно "мечтал", чтобы инициализация и деинициализация Asio были вынесены явно (например, в некоторый scoped guard класс). Вообще, мне кажется, любая библиотека, требующая инициализации/деинициализация должна позволять делать это явно (если не требовать). Ваше мнение?
Вот еще кое-что по теме, но из другого "королевства" — TBB initialization, termination, and resource management details, juicy and gory:
This means that auto-initialization, with all its convenience, may restrict your ability to control concurrency of parallel computations. The only consolation is that fortunately this is rarely an issue in practice.
Programs must be written for people to read, and only incidentally for machines to execute
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, о_О, Вы писали:
о_О>>Здравствуйте, jazzer, Вы писали:
J>>>Здравствуйте, о_О, Вы писали:
о_О>>>>>>в asio какое-то порно с глобальными переменными. в курсе, что WSAStartup вызывается так же и чем это грозит? J>>>>>багрепорт уже отправили им? о_О>>>>зачем? что я ему скажу? "эй, линуксоид, кто ж WSAStartup на глобальную переменную вешает?"
J>>>если уберешь "линуксоид" и приведешь вместо этого цитату из MSDN, а еще лучше, пример падающей программы — то да.
о_О>>нуу... эту проблему можно решить путем добавления флага компиляции ASIO_MANUAL_INITIALIZATION, но...
о_О>>*тут было очень много разоблачающего текста*
J>Давай ты это все изложишь на английском и трекере буста, а сюда ссылку? J>Я тебе даже помогу: J>https://svn.boost.org/trac/boost/newticket
Здравствуйте, abrarov, Вы писали:
A>Вообще, мне кажется, любая библиотека, требующая инициализации/деинициализация должна позволять делать это явно (если не требовать). Ваше мнение?
она обязана не производить инициализацию/деинициализацию автоматически, если используются системные библиотеки. это требование Windows, а требования API ОС надо соблюдать
но конкретно крис колхоф — линуксоид и такое порно у него уже 8 лет
Ну хотя бы с WSAStartup/WSACleanup там есть решение. Да. Что касается boost::asio::placeholders, то они мне "сразу не понравились". Перейду на boost::arg<> и на _N.
Programs must be written for people to read, and only incidentally for machines to execute
Здравствуйте, abrarov, Вы писали:
A>Давно "мечтал", чтобы инициализация и деинициализация Asio были вынесены явно (например, в некоторый scoped guard класс). Вообще, мне кажется, любая библиотека, требующая инициализации/деинициализация должна позволять делать это явно (если не требовать). Ваше мнение?
Полностью согласен.
Например, в стандартной библиотеке создаются глобальные объекты стандартных потоков ввода-вывода, так для этого есть специальный класс std::ios_base::Init (смотри [lib.ios::Init] в стандарте).
A>Вот еще кое-что по теме, но из другого "королевства" — TBB initialization, termination, and resource management details, juicy and gory: A>
A>This means that auto-initialization, with all its convenience, may restrict your ability to control concurrency of parallel computations. The only consolation is that fortunately this is rarely an issue in practice.
Да, я с этим сталкивался, гемор тот еще.
Хорошо, когда можешь управлять рождением потоков и проинициализировать все до того, как появятся первые потоки.
Но такое далеко не всегда бывает, и начинаются всякие веселые эффекты
Здравствуйте, jazzer, Вы писали:
J>Еще имеет смысл поднять шум в мейл-листе буста (boost-dev), там много народу это увидят и он уже не сможет так просто отмахнуться.
Об этом х/з сколько раз писали в рассылке по Asio (asio-users@sf.net).
Programs must be written for people to read, and only incidentally for machines to execute
Здравствуйте, abrarov, Вы писали:
A>Здравствуйте, о_О, Вы писали:
о_О>>с ним не о чем говорить: о_О>>https://svn.boost.org/trac/boost/ticket/3605
A>Ну хотя бы с WSAStartup/WSACleanup там есть решение. Да. Что касается boost::asio::placeholders, то они мне "сразу не понравились". Перейду на boost::arg<> и на _N.
а ты видел как async_resolve, async_connect сделаны? запускается один поток (1!) и делается getaddrinfo (аналогично connect), и если второй поток тоже делает запрос, то он виснет на мьютексе. вот это асинхронность по-линуксоидному ещё небось поток в глобальной переменной
Здравствуйте, abrarov, Вы писали:
A>Здравствуйте, о_О, Вы писали:
о_О>>но конкретно крис колхоф — линуксоид и такое порно у него уже 8 лет
A>Ммда. К сожалению, похоже на правду.
так глянь impl. я как увидел это в 2008, то ещё тогда решил, что в продакшн такое использовать нельзя. сомневаюсь, что если афтор уже 8 лет не может правильно инициализировать WinSock, то там что-то кардинально изменилось
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, о_О, Вы писали:
о_О>>с ним не о чем говорить: о_О>>https://svn.boost.org/trac/boost/ticket/3605
J>Еще имеет смысл поднять шум в мейл-листе буста (boost-dev), там много народу это увидят и он уже не сможет так просто отмахнуться.
я знаю эту библиотеку ещё до буста. после того как asio взяли в boost в 2008, афтор стал очень сильно гнуть пальцы.
з.ы. кстати некоторые дефайны ещё в 2009 были глючны — библиотека не собиралось. и это в официальных релизах буста. такие дела
Здравствуйте, о_О, Вы писали:
о_О>так глянь impl. я как увидел это в 2008, то ещё тогда решил, что в продакшн такое использовать нельзя. сомневаюсь, что если афтор уже 8 лет не может правильно инициализировать WinSock, то там что-то кардинально изменилось
Ну там, вроде, ничего сильно страшного нет.
Programs must be written for people to read, and only incidentally for machines to execute
Здравствуйте, о_О, Вы писали:
о_О>а ты видел как async_resolve, async_connect сделаны? запускается один поток (1!) и делается getaddrinfo (аналогично connect), и если второй поток тоже делает запрос, то он виснет на мьютексе. вот это асинхронность по-линуксоидному ещё небось поток в глобальной переменной
Насчет async_resolve — так это же вроде проблема WinSock, что нет асинхронного аналога. Всегда думал, что там очередь к одному рабочему потоку используется... Сейчас гляну.
Здравствуйте, abrarov, Вы писали:
A>Насчет async_resolve — так это же вроде проблема WinSock, что нет асинхронного аналога. Всегда думал, что там очередь к одному рабочему потоку используется... Сейчас гляну.
а пул потоков с менеждером, который эмулирует асинхронность, я должен писать? впрочем и писал в свое время, что оставалось то...
A>Насчет async_connect — решается легко.
ты не понял. там connect() вместо ConnectEx() т.е. опять синхронность. опять через 1 поток. опять убогие костыли
Здравствуйте, о_О, Вы писали:
о_О>я знаю эту библиотеку ещё до буста. после того как asio взяли в boost в 2008, афтор стал очень сильно гнуть пальцы.
Знаю как раз с того момента, как вошла в состав Boost C++ Libraries. Про "пальцы" слышу первый раз. Лично с автором не знаком, а в переписке ничего такого за ним не замечал.
о_О>з.ы. кстати некоторые дефайны ещё в 2009 были глючны — библиотека не собиралось. и это в официальных релизах буста. такие дела
Пробовал почти все релизы Boost.Asio и не замечал глюков, не дающих собираться (использовал header-only вариант) — можете уточнить релиз и проблему (включая платформу/компилятор/флаги компиляции)? Становится все интереснее.
Programs must be written for people to read, and only incidentally for machines to execute
Здравствуйте, abrarov, Вы писали:
A>Пробовал почти все релизы Boost.Asio и не замечал глюков, не дающих собираться (использовал header-only вариант) — можете уточнить релиз и проблему (включая платформу/компилятор/флаги компиляции)?
я не помню, я её забросил в 2009
A>Становится все интереснее.
интересно, почему?
Здравствуйте, abrarov, Вы писали:
A>Пробовал почти все релизы Boost.Asio и не замечал глюков, не дающих собираться (использовал header-only вариант) — можете уточнить релиз и проблему (включая платформу/компилятор/флаги компиляции)? Становится все интереснее.
да, вспомнил. мы же не бустовскую версию использовали. когда её включили в буст, стали выходить две версии и тут начался зоопарк
Здравствуйте, о_О, Вы писали:
о_О>а пул потоков с менеждером, который эмулирует асинхронность, я должен писать? впрочем и писал в свое время, что оставалось то...
Ну про async_resolve и async_connect (в Windows) в документации все честно расписано. Спасибо и за это (даже такое не у всех бывает).
о_О>ты не понял. там connect() вместо ConnectEx() т.е. опять синхронность. опять через 1 поток. опять убогие костыли
Это объясняется тем, что поддерживалась Windows 2000, на которой ConnectEx нет. Обойти-то легко (позволю себе повторить эту ссылку) средствами самой библиотеки Boost.Asio.
Насчет пула — не всем нужен пул внутренних (по отношению к пользователю Boost.Asio) потоков (опять дополнительные потоки!). Те, кому одного потока мало, естественно, пишут свой async_resolve. Это вполне нормально. Не поддерживается целевой платформой — вот вам минимальный/плохонький fallback и честная документация про это. "Хороший" вариант — уж как-нибудь сами. Зачем пихать в библиотеку "жирный" non native workaround.
Programs must be written for people to read, and only incidentally for machines to execute
Здравствуйте, о_О, Вы писали:
о_О>интересно, почему?
Идеального кода, конечно, не существует. Но в Boost.Asio качество вполне так ничего. Вот с asio::placeholders прямо какой-то epic fail получился. С WSAStartup/WSACleanup мне все понятно — многие не любят явные инициализации/деинициализации (когда я вводил это в свои библиотеки, меня заставляли выносить в static) — ну это хотя бы решабельно без изменения кода Boost.Asio.
Programs must be written for people to read, and only incidentally for machines to execute
Здравствуйте, о_О, Вы писали:
о_О>да, вспомнил. мы же не бустовскую версию использовали. когда её включили в буст, стали выходить две версии и тут начался зоопарк
Про проблемы с non-boost version где-то уже слышал. Смысл non-boost version (которая все равно требует наличия Boost) остается для меня загадкой.
Programs must be written for people to read, and only incidentally for machines to execute
Здравствуйте, о_О, Вы писали:
о_О>да, вспомнил. мы же не бустовскую версию использовали. когда её включили в буст
Кстати, в последней версии автор много чего добавил/улучшил/исправил — прогресс есть. Надежда на качественную C-like effective with low overhead C++ network library еще живет.
Programs must be written for people to read, and only incidentally for machines to execute
Здравствуйте, abrarov, Вы писали:
A>Здравствуйте, о_О, Вы писали:
о_О>>интересно, почему?
A>Идеального кода, конечно, не существует. Но в Boost.Asio качество вполне так ничего. Вот с asio::placeholders прямо какой-то epic fail получился. С WSAStartup/WSACleanup мне все понятно — многие не любят явные инициализации/деинициализации (когда я вводил это в свои библиотеки, меня заставляли выносить в static) — ну это хотя бы решабельно без изменения кода Boost.Asio.
архитектура хороша, спору нет. и вообще по сравнению с другими очень секси, но присутствуют непростительные вещи, что приходится брать натфиль и, как с ConnectEx, фигачить
Здравствуйте, abrarov, Вы писали:
A>Здравствуйте, о_О, Вы писали:
о_О>>да, вспомнил. мы же не бустовскую версию использовали. когда её включили в буст
A>Кстати, в последней версии автор много чего добавил/улучшил/исправил — прогресс есть. Надежда на качественную C-like effective with low overhead C++ network library еще живет.
последние версии (судя по логам) радуют, проверю на практике в 2012м