C ++共享内存泄漏,如何清除共享内存?

时间:2011-10-14 20:34:41

标签: c++ qt memory-management memory-leaks shared-memory

我正在使用Qt并尝试通过在 Linux(ubuntu)中应用this解决方案来实现单实例应用程序。问题是,如果应用程序意外完成(seg。错误或用户杀死它),共享内存将保持连接状态,其他任何进程都无法再次创建它。回想一下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(); 
}

您可以在此建议哪些解决方案?在流程最终​​完成后,如何确保共享内存被清除(或者通常使用的任何动词)。我需要在java函数中使用类似finally的东西:/

编辑:(解决方案)

我已经通过使用QSharedMemory并捕获SIGSEGV信号然后在信号处理程序中调用sharedMemory.detach()来实现所需的行为。

3 个答案:

答案 0 :(得分:5)

您可以捕获导致程序崩溃的信号,并使用调用QSharedMemory析构函数的处理程序。

答案 1 :(得分:1)

事实是,如果您的程序需要被杀死或有段错误,那么您无法真正做任何事情。共享内存不是确保UNIX / Linux下单个应用程序实例的最佳选择。请尝试使用信号量,因为它们会在应用程序终止后立即关闭。

编辑:

来自sem_close

的文档
  

所有打开的命名信号量都会在进程中自动关闭   终止,或执行(2)。

我还必须补充一点,确保单应用程序约束可能会对像linux这样的系统产生奇怪的后果 - 想象有人通过ssh使用X隧道进行登录并尝试启动你的应用程序 - 如果某人已经在使用它,它将无法启动。这将是相当混乱的。您是应用程序开发人员,如果您需要每个系统的每个用户甚至每个X-session阻止,那么您应该最了解。

如果您想使用每用户封锁,那么解决方案可能是在包含当前pid的用户主目录中添加隐藏文件。下一个应用程序将检查此文件,如果它存在并且/ proc / [pid] / exe链接指向当前二进制文件,则返回错误。

答案 2 :(得分:1)

您可以在程序终止后运行脚本,以手动清除系统上的共享内存,信号量等(我的是运行10.8的Mac Pro)。我在运行使用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