закрыть для текстового файла, вызывающего ошибку сегментации, и `обнаружен glibc` под Linux на C

#c #linux #text #segmentation-fault #glibc

#c #linux #текст #ошибка сегментации #glibc

Вопрос:

У меня есть класс log, этот класс содержит поток, определенный как: ofstream logfile и мьютекс, чтобы убедиться, что каждый раз только один поток записывает в файл (программа многопоточная). Класс определяется как:

 #define LOG_NAME "log.txt"

using namespace std;

class Log
{
private:
    pthread_mutex_t mutex_write;
    ofstream logfile;

public:
    Log();
    ~Log();
    void Write (string txt);
};
  

Конструктор является:

 Log::Log()
{
    pthread_mutex_init (amp;mutex_write,NULL);
    pthread_mutex_lock (amp;mutex_write);
    logfile.open(LOG_NAME, ios::out | ios::trunc);
    logfile << "Created log file named " << LOG_NAME << endl;
    pthread_mutex_unlock (amp;mutex_write);
}
  

Деструктор является:

 Log::~Log()
{
    logfile << "Closing log file" << endl;
    pthread_mutex_lock (amp;mutex_write);
    logfile.close();
    pthread_mutex_unlock (amp;mutex_write);
    pthread_mutex_destroy (amp;mutex_write);
}
  

и:

 void Log::Write (string txt)
{
    pthread_mutex_lock (amp;mutex_write);
    logfile << txt << endl;
    pthread_mutex_unlock (amp;mutex_write);
}
  

В некоторых случаях при вызове деструктора он не может выполнить строку logfile.close(); , поскольку в нем говорится, что он получает ошибку сегментации, или отображается сообщение:

 *** glibc detected *** corrupted double-linked list: 0x0000000000513eb0 ***
Abort
  

Это происходит не постоянно, кажется, что это происходит случайным образом, примерно в 10% случаев. Программа является многопоточной (под Linux).

Редактировать: пример использования: (где log — указатель на объект Log класса)

 stringstream str;
str.str("");
str << "Ant " << i << " was created at place: (" << x << "," << y << ")";
log->Write (str.str());
  

или, если строка содержит только текст knows

 log->Write ("Created board entity");
  

Комментарии:

1. Как этот объект журнала используется в потоках? Я предполагаю, что это общий объект. Можете ли вы предоставить нам какой-нибудь код, показывающий, как выглядят вызовы Write()?

2. Почему у вас есть защита от блокировки в вашем деструкторе? Либо в этот момент объект Log не должен использоваться, либо у вас есть более серьезные проблемы, о которых стоит беспокоиться…

3. @forsvarir, я добавил защиту в деструктор на всякий случай, потому что мы уже везде ставили мьютексы.

4. Повреждение кучи, подобное этому, обычно является результатом ошибки где-то перед кодом, в котором abort происходит.

5. Используйте ostringstream, а не stringstream.

Ответ №1:

Не уверен на 100%, но это может быть связано с повреждением памяти в любом месте кода. Чтобы разобраться в этой проблеме глубже, попробуйте запустить свою программу под Valgrind или путем проверки дампа ядра (убедитесь, что он включен — AFAIR ulimit -c unlimited).

Ответ №2:

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

Комментарии:

1. Поскольку проблема была обнаружена — короткие вопросы. Является ли журнал глобальным статическим объектом? Почему бы не использовать одну из рабочих фреймворков ведения журнала c в вашем проекте?

2. @Sergey: Во-первых, я не знал, что на C существуют фреймворки ведения журнала. Во-вторых, как вы можете видеть, класс log, который я написал, очень прост и легок в написании. У нас не было ошибок с ним (за исключением этого, который является ошибкой с потоковой передачей других частей, а не с самим журналом). Нам пришлось бы приложить больше усилий для изучения того, как использовать существующий класс, чем для написания этого.