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

C++ C++;共享内存泄漏,如何清除共享内存?,c++,qt,memory-management,memory-leaks,shared-memory,C++,Qt,Memory Management,Memory Leaks,Shared Memory,我正在使用Qt,并试图通过在Linux(ubuntu)中应用解决方案来实现一个单实例应用程序。问题是,如果应用程序意外完成(seg.fault或用户杀死它),共享内存将保持连接状态,其他进程无法再次创建它。从QSharedMemory文档召回: Unix:QSharedMemory“拥有”共享内存段。最后一次是什么时候 将QSharedMemory实例附加到 特定共享内存段通过以下方式与该段分离: Unix内核在销毁其QSharedMemory实例后,发布 共享内存段。但如果最后一个线程或进程崩

我正在使用Qt,并试图通过在Linux(ubuntu)中应用解决方案来实现一个单实例应用程序。问题是,如果应用程序意外完成(seg.fault或用户杀死它),共享内存将保持连接状态,其他进程无法再次创建它。从QSharedMemory文档召回:

Unix:QSharedMemory“拥有”共享内存段。最后一次是什么时候 将QSharedMemory实例附加到 特定共享内存段通过以下方式与该段分离: Unix内核在销毁其QSharedMemory实例后,发布 共享内存段。但如果最后一个线程或进程崩溃 在不运行QSharedMemory析构函数的情况下,共享内存 这一段在撞车中幸存了下来

intmain(intargc,char*argv[])
{
质量保证申请a(argc、argv);
//确保CEVIGEC应用程序的单实例
QSharedMemory共享(ApplicationConstants::
如果(!shared.create(512,QSharedMemory::ReadWrite))
{
//QMessageBox-msgBox;
QMessageBox::critical(0,QObject::tr(“应用程序已在运行!”),QObject::tr(“应用程序已在运行!”),QMessageBox::Ok,QMessageBox::Ok);

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

事实是,如果您的程序需要终止或出现segfault,那么您实际上无法对此采取任何措施。共享内存不是确保UNIX/Linux下应用程序的单个实例的最佳选择。请尝试使用信号量s,因为一旦应用程序终止,它们就会关闭

编辑:

根据

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

我还必须补充一点,确保单一应用程序约束可能会在linux这样的系统上产生奇怪的后果-想象有人通过ssh使用X隧道登录并试图启动你的应用程序-如果有人已经在使用它,它将不会启动。这将是相当确定的。你是应用程序开发人员,应该最清楚你是否需要每个系统-用户或甚至每X会话封锁


若要使用每用户封锁,则解决方案可能是在用户主目录中添加包含当前pid的隐藏文件。下一个应用程序将检查此文件,以及它是否存在和/proc/[pid]/exe链接指向当前二进制文件,然后返回错误。

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

您可能不应该尝试使应用程序的行为与操作系统和用户期望应用程序的行为不同。如果操作系统的标准行为是用户期望能够启动多个实例(如在Windows和Linux上),那么他们应该能够启动多个实例。如果标准行为是强制启动单个实例(如在Mac上),则t然后让操作系统自己强制执行。操作系统中没有此类行为的标准。这完全取决于应用程序53:有很多应用程序只允许您启动一个实例,有时这是合乎逻辑的做法。@至少有些操作系统是这样做的,与操作系统规定的一致行为相反的是wro另一方面,如果操作系统的用户环境没有任何标准,应用程序只是有一大堆不同的行为,那么去做吧,做你想做的任何事情。@rubenvb是的,我个人喜欢在我使用的应用程序中这样做。但是一些操作系统的用户环境设置了与我个人偏好相反的标准,大概是因为它们迎合了具有不同偏好的用户。是的,例如,对于类Foo的对象f:
f.~Foo()
。但您必须仅在语言不会自动调用析构函数的情况下这样做。是的,您可以-但我不知道您是否可以依赖信号处理程序中与qt相关的任何内容,因为此类处理程序应该是自包含的,而不依赖于程序中的任何其他内容。C++11“当接收到信号中断抽象机器的处理时,对象的值既不是1.)类型的
volatile std::sig_atomic_t
也不是2.)类型的无锁原子对象(29.4),在信号处理程序执行期间未指定,并且处理程序修改的任何不属于这两个类别的对象的值都将变为未定义。"我不知道
QSharedMemory
是否符合这些要求。也许您想要链接的另一个问题中投票最多的答案所建议的
QtSingleApplication
。不幸的是,
QtSingleApplication
不再被维护,现在有点不受欢迎。但如果崩溃的信号量重新出现,同样的问题也会出现通过组合QSharedMemory和捕获SIGSEGV信号,然后调用sharedMemory.detach()实现了所需的行为但在您的编辑中,您提醒我,在多用户系统中,如果两个或更多用户尝试运行该应用程序,则会出现问题。这是一个依赖于gui的应用程序,即使使用-X param,也没有人会通过ssh运行该应用程序,但他们可能希望在同一台计算机上同时运行该应用程序。感谢您指出这一点
#!/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