gpt4 book ai didi

c++ - Linux 共享库中的单例无法按预期工作

转载 作者:太空狗 更新时间:2023-10-29 12:39:10 26 4
gpt4 key购买 nike

我已经创建了包含单例类的简单共享库,我希望这个类能够相应地运行,也就是说,对于所有使用它的应用程序来说,它将是一个真正的单例。但事实证明,它的工作方式不同。每个使用我的共享库的应用程序都会创建自己的单例实例,这根本不符合我的计划。

这是共享库的代码:

singleton.h

#ifndef SINGLETON_H
#define SINGLETON_H

#if defined _WIN32 || defined __CYGWIN__
#ifdef BUILDING_DLL
#ifdef __GNUC__
#define DLL_PUBLIC __attribute__ ((dllexport))
#else
#define DLL_PUBLIC __declspec(dllexport) // Note: actually gcc seems to also supports this syntax.
#endif
#else
#ifdef __GNUC__
#define DLL_PUBLIC __attribute__ ((dllimport))
#else
#define DLL_PUBLIC __declspec(dllimport) // Note: actually gcc seems to also supports this syntax.
#endif
#endif
#define DLL_LOCAL
#else
#if __GNUC__ >= 4
#define DLL_PUBLIC __attribute__ ((visibility ("default")))
#define DLL_LOCAL __attribute__ ((visibility ("hidden")))
#else
#define DLL_PUBLIC
#define DLL_LOCAL
#endif
#endif

class DLL_PUBLIC Singleton
{
public:
static Singleton &instance();
int test();

private:
Singleton();
int m_num;
};

#endif

单例.cpp

#include "singleton.h"

Singleton &Singleton::instance()
{
static Singleton singleton;
return singleton;
}

Singleton::Singleton() :
m_num(0)
{ }

int Singleton::test()
{
return ++m_num;
}

编译链接如下:

g++ -c -pipe -fPIC -o singleton.o singleton.cpp
g++ -rdynamic -export-dynamic -shared -Wl,-soname,libSingletonLib.so.1 -o libSingletonLib.so.1.0.0 singleton.o

小型测试工具:

main.cpp

#include <stdio.h>
#include "singleton.h"

int main(int argc, char *argv[])
{
int num = Singleton::instance().test();
printf("num: %d", num);
getchar();

return 0;
}

以及编译和链接选项:

g++ -c -pipe -g -std=gnu++11 -Wall -W -fPIC -o main.o main.cpp
g++ -Wl -o ../SingletonTest main.o -L.. -lSingletonLib

现在我运行了测试应用程序的 2 个实例,因此我希望它们都使用单例并且数量会增加。但出乎意料的输出是:

一审:

./SingletonTest 
num: 1

二审:

./SingletonTest
num: 1

注意:第一个应用程序在第二个应用程序启动时仍在运行。

据我了解,应用程序的每个实例都会创建不同的单例实例。

我怎样才能避免这种情况,使所有链接到同一个共享库的实例都只使用一个单例?

我使用:

  • Ubuntu 18.04

  • gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0

更新:好的,看来我必须使用共享内存或一些进程间通信。我以前从未使用过它,所以我会重新表述这个问题:如何将一个且只有一个单例用于多个进程?我怎样才能把它放在共享内存或其他地方?

最佳答案

好的,经过长时间的搜索,我想我已经找到了解决方案(或者可能是解决方法)。出于某种原因,我完全忽略了共享库共享代码但不共享数据。每个使用同一个共享库的应用程序都会创建它的单例拷贝。所以我明白我需要按照评论中的建议使用 IPC(感谢@Gojita 和@Mayur)。

这就是我得到的代码:

#include <new>
#include <errno.h>

...

Singleton &Singleton::instance()
{
//static Singleton instance;
//return instance;
static Singleton* instance = getSharedMemory();
return *instance;
}

Singleton * Singleton::getSharedMemory()
{
Singleton * instance = nullptr;
bool already_exists = false;

int shm = shm_open("my_memory", O_CREAT | O_RDWR | O_EXCL, 0777);
if(shm == -1)
{
if(errno == EEXIST)
{
already_exists = true;
shm = shm_open("my_memory", O_CREAT | O_RDWR , 0777);
}
if(shm == -1)
{
perror("shm_open error");
return nullptr;
}
}

void *addr = mmap(nullptr, sizeof(Singleton) + 1, PROT_WRITE | PROT_READ, MAP_SHARED, shm, 0);
if(!already_exists)
{
if (ftruncate(shm, sizeof(Singleton) + 1) == -1)
{
perror("ftruncate error");
return nullptr;
}
instance = new(addr) Singleton;
}
else
instance = reinterpret_cast<Singleton *>(addr);


return instance;
}

注意:在下面的代码中,我创建了共享内存区域(名为“my_memory”)。如果内存已经分配(标志 O_EXCL 完成工作)我就使用它,否则我设置它的大小(使用 ftruncate)并使用在内存中放置新的来创建我的单例。作为奖励 - 您可以退出应用程序,然后再次进入并按原样使用单例 - 该类仍保留在内存中。可以通过调用 munmapshm_unlink 或通过重新启动操作系统来释放内存。

关于c++ - Linux 共享库中的单例无法按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55372908/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com