Ответ 1
Я попытался использовать boost:: interprocess для проекта и ушел со смешанными чувствами. Мое основное недоумение - это дизайн boost:: offset_ptr и то, как он обрабатывает значения NULL - короче говоря, boost:: interprocess может сделать диагностику ошибок NULL-указателей очень болезненными. Проблема в том, что сегмент разделяемой памяти отображается где-то посередине адресного пространства вашего процесса, а это означает, что "NULL" offset_ptr, когда разыменовывается, укажет на допустимую ячейку памяти, поэтому ваше приложение не будет segfault. Это означает, что когда ваше приложение, наконец, сработает, оно может быть слишком долго после ошибки, что очень сложно отладить.
Но все ухудшается. Мьютексы и условия, которые используют внутреннее использование: interprocess, сохраняются в начале сегмента. Поэтому, если вы случайно напишите в some_null_offset_ptr- > some_member, вы начнете перезаписывать внутреннюю машину сегмента boost:: interprocess и получить совершенно странное и труднопонятное поведение. Написание кода, который координирует несколько процессов и имеет дело с возможными условиями гонки, может быть жестким само по себе, поэтому он был вдвойне сумасшедшим.
В итоге я написал свою собственную минимальную библиотеку разделяемой памяти и использовал системный вызов POSIX mprotect, чтобы сделать первую страницу моих разделяемых сегментов памяти нечитаемой и невоспроизводящейся, что сразу же вызвало ошибки NULL (вы теряете страницу памяти, но такую маленькая жертва стоит того, если вы не на встроенной системе). Вы можете попробовать использовать boost:: interprocess, но все же вручную вызывать mprotect, но это не сработает, потому что boost ожидает, что он сможет записать эту внутреннюю информацию, хранящуюся в начале сегмента.
Наконец, offset_ptr предположим, что вы храните указатели в сегменте общей памяти в других точках одного и того же сегмента разделяемой памяти. Если вы знаете, что у вас будет несколько разделов разделяемой памяти (я знал, что это будет так, потому что для меня, потому что у меня был один записываемый сегмент и 1 только для чтения сегмент), который будет хранить указатели друг в друга, offset_ptr будет мешать вы должны сделать кучу ручных преобразований. В моей библиотеке разделяемой памяти я создал шаблонный SegmentPtr<i>
класс, где SegmentPtr<0>
был бы указателем на один сегмент, SegmentPtr<1>
был бы указателем на другой сегмент и т.д., Чтобы их нельзя было перепутать (вы можете сделать это только хотя, если вы знаете количество сегментов во время компиляции).
Вам нужно взвесить стоимость реализации всего, что вам нужно, и дополнительное время отладки, которое вы собираетесь потратить на отслеживание ошибок NULL и, возможно, смешение указателей на разные сегменты (последнее не обязательно для вас). Для меня это стоило того, что я сам реализовал, но я не сильно использовал структуры данных boost:: interprocess, поэтому это было явно стоит. Если библиотеке разрешено быть открытым исходным кодом в будущем (не до меня), я обновляю ссылку, но пока не задерживаю дыхание, p
Что касается вашего коллеги: я не испытывал никакой нестабильности или ошибок в boost:: interprocess. Я просто думаю, что его дизайн затрудняет поиск ошибок в вашем собственном коде.