Использование статических членов в Static Lib и DLL — сбрасывается значение члена

У меня есть решение с 3 проектами:

  • Lib1 (статическая библиотека)
  • Dll1 (динамическая библиотека)
  • App1 (пустое приложение Магазина Windows, может быть любого типа приложения)

Lib1 содержит следующее:

Export.h

#pragma once

#ifdef DLL_EXPORT
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif

Lib1.h

#pragma once
#include "Export.h"
class Member { };

class EXPORT Base {
public:
static Member* GetStaticMember();
virtual void SetMember(Member* member) = 0;

protected:
static Member* m_member;
};

class Worker {
public:
void DoSomething();
};

Lib1.cpp

#include "pch.h"#include "Lib1.h"
Member* Base::m_member;

Member* Base::GetStaticMember() {
return m_member;
}

void Worker::DoSomething() {
Member* test = Base::GetStaticMember(); // RETURNS 0
}

Dll1 содержит следующее

Dll1.h

#pragma once
#include "Lib1.h"#include "Export.h"
class EXPORT ChildA : public Base {
public:
virtual void SetMember(Member* member) override;
};

Dll1.cpp

#include "pch.h"#include "Dll1.h"
void ChildA::SetMember(Member* member) {
Base::m_member = member;

Member* test = Base::GetStaticMember(); // RETURNS CORRECT ADDRESS
}

Приложение 1 содержит следующее

Member* member = new Member();
ChildA* childa = new ChildA();
childa->SetMember(member); // Base::GetStaticMember() inside this RETURNS CORRECT ADDRESS

Worker* worker = new Worker();
worker->DoSomething(); // Base::GetStaticMember() inside this RETURNS 0

При прохождении в отладчике Base :: GetStaticMember () возвращает правильный адрес члену после того, как он установлен (но все еще внутри childa-> SetMember (). Как только OUTSIDE childa, Base :: GetStaticMember () возвращает 0. Когда внутри worker-> DoSomething (), Base :: GetStaticMember () также возвращает 0. Может кто-нибудь объяснить мне, в чем причина и как это исправить, чтобы получить доступ к Base :: GetStaticMember () либо снаружи, либо внутри методов из dll или lib вернет правильный адрес а не 0?

3

Решение

Если вы используете статическую библиотеку, связанную с несколькими DLL и / или вашим EXE, каждая из них получит свою своя статическая переменная-член. Подумайте о механике того, как происходит * фаза связи каждого из них, и вы поймете, почему.

Вы Можно превратите ваши статические переменные в указатели, ссылающиеся на разделяемую память, поддерживаемую файлом с отображенной памятью, но я предупреждаю вас, что управлять им становится сложно. Я сделал это, поддерживая временный файл карты памяти, используя имя класса + member + pid в качестве имени отображения (примечание: pid должен был позволить нескольким процессам запускаться без надавливания друг на друга совместно используемой mem). это сработало на удивление хорошо.

2

Другие решения

Вы должны связать lib1 только с Dll1 или с App1, не оба.

Теперь у вас есть Base::_member определенный и то и другое в вашем Dll1 а также App1,

Как вы определили Base учебный класс __dllexport/__dllimport, оно использует Dll1 статический член, но вы не объявлены Worker с любыми атрибутами, и он использует местный статический член.

Я полагаю, вы должны указать атрибуты для Worker и не связывать App1 с Lib1

0

По вопросам рекламы [email protected]