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

发布于 2024-12-10 13:29:05 字数 1335 浏览 0 评论 0原文

我正在使用 Qt 并尝试通过应用 Linux(ubuntu) 中的此解决方案。问题是,如果应用程序意外完成(例如,错误或用户终止它),共享内存仍保持连接状态,并且其他进程无法再次创建它。回顾 QSharedMemory 文档:

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 信号然后调用共享内存实现了所需的行为。信号处理程序中的 detach() 。

I am using Qt and trying to achieve a single instance application by applying this solution in Linux(ubuntu). The problem is that if the application unexpectedly finishes(seg. fault or user kills it) the shared memory remains attached and no other process can create it again. Recall from QSharedMemory doc:

Unix: QSharedMemory "owns" the shared memory segment. When the last
thread or process that has an instance of QSharedMemory attached to a
particular shared memory segment detaches from the segment by
destroying its instance of QSharedMemory, the Unix kernel release the
shared memory segment. But if that last thread or process crashes
without running the QSharedMemory destructor, the shared memory
segment survives the crash.

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(); 
}

What solutions can you suggest here? How can I assure that the shared memory is cleared(or whatever verb used generally) after the process eventually finishes. I need something like finally in java all around the main function :/

EDIT: (Solution)

I have achieved the desired behavior by using QSharedMemory and catching SIGSEGV signal then call sharedMemory.detach() in the signal handler.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

╭ゆ眷念 2024-12-17 13:29:05

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

You can catch the signals that crash your program and use a handler that calls the QSharedMemory destructor.

旧竹 2024-12-17 13:29:05

事实是,如果您的程序需要被终止或出现段错误,那么您实际上无能为力。共享内存并不是确保 UNIX/Linux 下应用程序单实例的最佳选择。尝试使用信号量来代替,因为一旦应用程序终止它们就会关闭。

编辑:

来自 sem_close 的文档

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

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

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

Truth is that if your program needs to be killed or has a segfault, then you cannot really do anything about it. Shared memory is not the best choice for ensuring single instance of appliction under UNIX/Linux. Try using semaphores instead, as they are getting closed as soon as your application terminates.

EDIT:

From documentation of sem_close

All open named semaphores are automatically closed on process
termination, or upon execve(2).

I also must add that ensuring single-app contraint might have weird consequences on system like linux - imagine somebody logged via ssh with X tunneling and trying to start your app - if somebody is already using it, it will not start. This will be rather confisunig. You are application developer and should know best if you need per-system per-user or even per-X-session blockade.

If you want to use per-user blockade, then solution might be to add hidden file in user home directory containing current pid. Next application will check for this file, and if it exists AND /proc/[pid]/exe link points to current binary, then return error.

っ〆星空下的拥抱 2024-12-17 13:29:05

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

You could always run a script after termination of your program to manually clear the shared memory, semaphores, etc. on your system (mine is a Mac Pro running 10.8). I have inserted a script I use for this when running programs that use QSharedMemory, and use it when the program quits unexpectedly and leaves the shared memory instances "hanging".

Keep in mind this will remove all shared memory instances associated with your user name. If you have multiple programs running and using shared memory instances, you should either wait until every program is done, or adjust the script as needed to only delete the shared memory instances that were created by your program.

#!/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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文