Утечка разделяемой памяти C ++, как очистить разделяемую память? - PullRequest
5 голосов
/ 15 октября 2011

Я использую Qt и пытаюсь создать приложение для одного экземпляра, применяя это решение в Linux (ubuntu) .Проблема заключается в том, что если приложение неожиданно завершает работу (ошибка сегмента или пользователь убивает его), общая память остается подключенной, и никакой другой процесс не может создать ее снова.Отзыв из QSharedMemory doc:

Unix: QSharedMemory "владеет" сегментом совместно используемой памяти.Когда последний поток или процесс, который имеет экземпляр QSharedMemory, подключенный к определенному сегменту совместно используемой памяти, отсоединяется от сегмента путем уничтожения своего экземпляра QSharedMemory, ядро ​​Unix освобождает сегмент совместно используемой памяти.Но если последний поток или процесс завершается сбоем без запуска деструктора QSharedMemory, сегмент общей памяти переживает сбой.

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // Ensure single instanse of Cevirgec application
    QSharedMemory shared(ApplicationConstants::

    if( !shared.create( 512, QSharedMemory::ReadWrite) )
    {
      // QMessageBox msgBox;
      QMessageBox::critical(0, QObject::tr("application is already running!"), QObject::tr("application is already running!"), QMessageBox::Ok, QMessageBox::Ok);
      qCritical() << "application is already running!";

      exit(0);
    }
    else {
        qDebug() << "application staring...";
    }
    return a.exec(); 
}

Какие решения вы можете предложить здесь?Как я могу гарантировать, что разделяемая память очищается (или какой-либо глагол, используемый в целом) после того, как процесс в конце концов завершится.Мне нужно что-то вроде finally в Java по всей основной функции: /

РЕДАКТИРОВАТЬ: (Решение)

Я добился желаемого поведения с помощью QSharedMemory и перехватаСигнал SIGSEGV затем вызывает sharedMemory.detach () в обработчике сигнала.

Ответы [ 3 ]

5 голосов
/ 15 октября 2011

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

1 голос
/ 13 марта 2013

Вы всегда можете запустить сценарий после завершения вашей программы, чтобы вручную очистить разделяемую память, семафоры и т. Д. В вашей системе (у меня Mac Pro 10.8). Я вставил скрипт, который я использую для этого, при запуске программ, использующих QSharedMemory, и использую его, когда программа неожиданно завершает работу и оставляет экземпляры общей памяти «зависшими».

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

#!/bin/bash

ME=$(whoami)

IPCS_S=$(ipcs -s | grep $ME | sed "s/  / /g" | cut -f2 -d " ")
IPCS_M=$(ipcs -m | grep $ME | sed "s/  / /g" | cut -f2 -d " ")
IPCS_Q=$(ipcs -q | grep $ME | sed "s/  / /g" | cut -f2 -d " ")

echo "Clearing Semaphores"
for id in $IPCS_S
do
    ipcrm -s $id
done

echo "Clearing Shared Memory"
for id in $IPCS_M 
do
    ipcrm -m $id
done

echo "Clearing Message Queues"
for id in $IPCS_Q
do
    ipcrm -q $id
done
1 голос
/ 15 октября 2011

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

РЕДАКТИРОВАТЬ:

Из документации sem_close

Все открытые именованные семафоры автоматически закрываются при завершении процесса или при выполнении execve (2).

Я также должен добавить, что обеспечение несоответствия одному приложению может иметь странные последствия для системы, такой как Linux - представьте, что кто-то вошел черезSSH с туннелированием X и попыткой запустить ваше приложение - если кто-то уже использует его, оно не запустится.Это будет довольно конфиденциально.Вы разработчик приложений и должны лучше знать, нужна ли вам блокировка для каждого пользователя или даже для каждого сеанса.

Если вы хотите использовать индивидуальную блокировку пользователя, то решением может быть добавление скрытого файла в домашний каталог пользователя, содержащий текущий pid.Следующее приложение проверит этот файл, и, если он существует, ссылка / / proc / [pid] / exe указывает на текущий двоичный файл, а затем вернет ошибку.

...