- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这是定义模板的头文件:根据一些答案,我进行了修改以使模板单线程安全。但程序仍然崩溃,所以我相信这里的重点不应该是模板是否是线程安全的。这是关于当 C1 继承自 CBase 和 Singleton 时发生的情况。显然,当C1尝试调用其父类CBase的成员变量的函数时,程序崩溃了。在我看来,当多重继承和单一模板一起使用时,内存中的某些东西会变得困惑。
#ifndef _T_SINGLETON_HH_
#define _T_SINGLETON_HH_
template <class T>
class Singleton
{
public:
static T* getInstance()
{
static T instance_;
return &instance_;
}
template <class A>
static T* getInstance(A a)
{
static T instance_(a);
return &instance_;
}
protected:
Singleton() {}
virtual ~Singleton() {}
private:
Singleton(Singleton const&);
Singleton& operator=(Singleton const&);
};
#endif // _T_SINGLETON_HH_ //
以下是该模板的使用方式:
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include "singleton.hh"
using namespace std;
class X;
class X1;
class ABase;
class BBase;
class BB;
class CBase;
class X {
public:
virtual int getX() = 0;
};
class X1 : public X {
public:
int getX() { return 1; }
};
class Timer
{
private:
static Timer* t_;
BBase* b_;
Timer();
static void* go_helper(void* context);
void go();
public:
virtual ~Timer() {}
static Timer* getInstance();
void subscribe(BBase* b);
void unsubscribe(BBase* b) { b_ = NULL; }
};
class CBase {
public:
CBase(BB& bb) : bb_(bb) {}
virtual void run() = 0;
protected:
BB& bb_;
};
class C1 : public CBase,
public Singleton<C1>
{
public:
C1(BB& bb) : CBase(bb) {}
void run();
};
class BBase {
public:
BBase(ABase& a) : a_(a) { Timer::getInstance()->subscribe(this); }
virtual ~BBase() { Timer::getInstance()->unsubscribe(this); }
virtual void run() = 0;
protected:
ABase& a_;
};
class BB : public BBase {
public:
BB(ABase& a) : BBase(a) {
c = C1::getInstance(*this);
// c = new C1(*this); IF WE USE THIS INSTEAD, THEN IT WILL WORK
}
int getX();
void run();
private:
CBase* c;
};
class ABase {
public:
ABase() {
x = new X1;
b = new BB(*this);
}
void run();
int getX() { return x->getX(); }
private:
X* x;
BBase* b;
};
Timer* Timer::t_ = NULL;
Timer::Timer() : b_(NULL)
{
pthread_t th;
pthread_create(&th, NULL, &Timer::go_helper, this);
}
Timer*
Timer::getInstance() {
if (t_ == NULL)
t_ = new Timer;
return t_;
}
void
Timer::subscribe(BBase* b) { b_ = b; }
void*
Timer::go_helper(void* context) {
Timer *t = reinterpret_cast<Timer*>(context);
t->go();
return NULL;
}
void
Timer::go()
{
while(1) {
sleep(1);
if (b_) b_->run();
}
}
void ABase::run() {
cout << __PRETTY_FUNCTION__ << getX() << endl;
cout << __PRETTY_FUNCTION__ << x->getX() << endl;
b->run();
while(1)
sleep(1);
}
int BB::getX() {
return a_.getX();
}
void BB::run() {
cout << __PRETTY_FUNCTION__ << endl;
c->run();
}
void C1::run() {
cout << __PRETTY_FUNCTION__ << bb_.getX() << endl;
}
int main()
{
ABase* a = new ABase;
a->run();
}
如果您仍然认为这是一个线程安全问题,那么这里是使用模板的简化单线程版本:
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include "singleton.hh"
using namespace std;
class X;
class X1;
class ABase;
class BBase;
class BB;
class CBase;
class X {
public:
virtual int getX() = 0;
};
class X1 : public X {
public:
int getX() { return 1; }
};
class CBase {
public:
CBase(BB& bb) : bb_(bb) {}
virtual void run() = 0;
protected:
BB& bb_;
};
class C1 : public CBase,
public Singleton<C1>
{
public:
C1(BB& bb) : CBase(bb) {}
void run();
};
class BBase {
public:
BBase(ABase& a) : a_(a) { }
virtual ~BBase() { }
virtual void run() = 0;
protected:
ABase& a_;
};
class BB : public BBase {
public:
BB(ABase& a) : BBase(a) {
c = C1::getInstance(*this);
// c = new C1(*this);
}
int getX();
void run();
private:
CBase* c;
};
class ABase {
public:
ABase() {
x = new X1;
b = new BB(*this);
}
void run();
int getX() { return x->getX(); }
private:
X* x;
BBase* b;
};
void ABase::run() {
cout << __PRETTY_FUNCTION__ << getX() << endl;
cout << __PRETTY_FUNCTION__ << x->getX() << endl;
b->run();
while(1)
sleep(1);
}
int BB::getX() {
return a_.getX();
}
void BB::run() {
cout << __PRETTY_FUNCTION__ << endl;
c->run();
}
void C1::run() {
cout << __PRETTY_FUNCTION__ << bb_.getX() << endl;
}
当我运行这个程序时,它崩溃了:
void ABase::run()1
void ABase::run()1
virtual void BB::run()
zsh: segmentation fault (core dumped) ./a.out
这里是GDB给出的堆栈信息:
#0 0x00000000004012ba in ABase::getX (this=0x1) at tst_sigill.cc:89
89 int getX() { return x->getX(); }
[Current thread is 1 (Thread 0x7faa0f050740 (LWP 5351))]
(gdb) bt
#0 0x00000000004012ba in ABase::getX (this=0x1) at tst_sigill.cc:89
#1 0x0000000000400e0c in BB::getX (this=0x7ffed6e821f0) at tst_sigill.cc:138
#2 0x0000000000400e71 in C1::run (this=0xaeedd0) at tst_sigill.cc:146
#3 0x0000000000400e51 in BB::run (this=0xaeec60) at tst_sigill.cc:142
#4 0x0000000000400de3 in ABase::run (this=0xaeec20) at tst_sigill.cc:132
#5 0x0000000000400ed1 in main () at tst_sigill.cc:152
由于某种未知的原因,传递给 BB::getX 和 ABase::getX 的指针被搞乱了。我看不出代码有什么问题。
最佳答案
嗯,主要问题似乎是您的 getInstance()
实现不是线程安全的。
我建议忘记所有 construct()
/destruct()
内容,并将其留给 ABI 提供的 CRT0 代码。
您应该使用 Scott Meyer's Singleton 之后的实现保证线程安全(至少对于当前标准):
template <class T>
class Singleton {
public:
static T& getInstance() {
static T instance_;
return instance_;
}
protected:
Singleton() {}
virtual ~Singleton() {}
Singleton(Singleton const&) = delete;
Singleton& operator=(Singleton const&) = delete;
};
如果以后需要更改任何可以异步访问的Singleton
属性,请记住还要提供线程安全操作。
您可以使用模板单例基础来支持这一点,例如:
template <class T>
class Singleton {
// ...
protected:
mutable std::mutex internalDataGuard;
};
class C1 : public CBase, public Singleton<C1> {
public:
C1(BB& bb) : CBase(bb) {}
void run();
void setSomeData(T data) {
std::unique_lock(Singleton<C1>::internalDataGuard);
// change internal data member ...
}
const T& getSomeData() const {
std::unique_lock(Singleton<C1>::internalDataGuard);
// return internal data member ...
}
};
关于c++ - 为什么单例模板会使我的程序崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37444732/
我最近购买了《C 编程语言》并尝试了 Ex 1-8这是代码 #include #include #include /* * */ int main() { int nl,nt,nb;
早上好!我有一个变量“var”,可能为 0。我检查该变量是否为空,如果不是,我将该变量保存在 php session 中,然后调用另一个页面。在这个新页面中,我检查我创建的 session 是否为空,
我正在努力完成 Learn Python the Hard Way ex.25,但我无法理解某些事情。这是脚本: def break_words(stuff): """this functio
我是一名优秀的程序员,十分优秀!