Как избежать SIGSEGV?

Я пишу клиент-серверный демон, который должен принимать и переводить определенные форматы сообщений, проверять их, чтобы отправить все действия в БД. Программа многопоточная. Итак, я начал работать и начал получать SIGSEGV в некоторых случаях. Поэтому мне пришлось переделать мою программу и начать все сначала.
Мне интересно, есть ли какие-либо «лучшие практики» или советы о том, как минимизировать риск SIGSEGV?
Я знаю, что каждый указатель должен быть проверен перед использованием и NULLED после удаления, но если есть какой-либо высокий уровень, советы по дизайну?

Постскриптум Извините, если мой вопрос достаточно глупый, но я погуглил по этой теме и не нашел каких-либо разумных статей на эту тему. Все ваши мнения приветствуются.

1

Решение

Параллельность может быть источником множества проблем по-разному, и SIGSEV является одной из проблем.
Начинающий может передать указатель Data* p; в два потока, и перед выходом заставьте их выполнить этот код.

if(p){
delete p->data;
delete p;
p = NULL;
}

Вам просто нужно, чтобы оба потока видели p как ненулевое, чтобы иметь возможность иметь сценарий SIGSEV. Использование стандартных контейнеров или умных указателей, как указал @jogojapan, может смягчить эту проблему.

2

Другие решения

Основными источниками ошибок сегментации являются

  • Неинициализированные указатели (или неинициализированные переменные в целом)
  • Вне доступа к массивам
  • Арифметика плохо закодированных указателей

Основные стратегии борьбы с этим включают в себя:

  • Всегда инициализируйте ваши переменные, в частности указатели
  • Избегайте голых указателей (предпочитайте умные указатели, такие как std::unique_ptr или же std::shared_ptr для указателей, которые владеют данными, и использовать итераторы в стандартные контейнеры, если вы хотите просто точка на вещи)
  • Используйте стандартные контейнеры (например, std::vector) вместо массивов и арифметики указателей

Как упоминалось в комментариях, плохо закодированный параллелизм или распараллеливание могут вызывать ошибки сегментации (и многие другие проблемы), так же, как это могут делать неинициализированные переменные, поскольку они могут привести к неожиданному изменению значения переменной. Общие стратегии для борьбы с этим включают в себя:

  • Избегайте общих данных — предпочитайте сообщения / очереди для связи между потоками
  • Если у вас есть общие данные, и по крайней мере один поток записывает в эти данные, используйте мьютексы, std::atomic или аналогичный для защиты

Однако в некоторых случаях оба могут означать, что вы потеряете значительные преимущества в производительности. Правильные параллельные алгоритмы — это вопрос тщательного анализа и проектирования.

2

По вопросам рекламы [email protected]