7

I have a solution set up with 3 projects:

  • Lib1 (A static library)
  • Dll1 (A dynamic library)
  • App1 (A Blank Windows Store application, could be any application type)

Lib1 contains the following:

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 contains the following

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 } 

App1 contains the following

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 

The Problem

When stepping through in the debugger, Base::GetStaticMember() returns the correct address to the member after it is set (but still while inside childa->SetMember(). Once OUTSIDE childa, Base::GetStaticMember() returns 0 instead. When inside worker->DoSomething(), Base::GetStaticMember() is also returning 0. Can anyone explain to me what the cause of this is and how to fix it so that accessing Base::GetStaticMember() either outside or inside methods of the Dll or Lib will return the correct address and not 0?

4
  • Does App1 link with Lib1? Commented Oct 20, 2012 at 18:55
  • @Lol4t0 I'm assuming yes, which is where the problem is coming from, likely. Commented Oct 20, 2012 at 19:01
  • Yes, both Dll1.lib and Lib1.lib are linked to App1. Lib1.lib is also linked into Dll1. Should App1 only link to the dll? If so then I have no access to the worker->DoSomething() method. Commented Oct 20, 2012 at 19:07
  • Mike, see my answer below, and if you need some sample code on setting up a shared-memory-mapped variable I can try and dig some up for you. The memory mapping isn't overly complicated, just a little busy (its windows; that tells it all). Commented Oct 20, 2012 at 19:11

2 Answers 2

3

If you're using a static lib linked to multiple DLL's and/or your EXE, each will get its own static member variable. Think of the mechanics of how the *link phase of each of these happens and you'll see why.

You can turn your static vars into pointers referencing shared memory backed by a memory mapped file, but I warn you it gets tricky to manage. I've done it by maintaining a temp memory-map-file using the name of the class+member+pid as the mapping name (note: the pid was to allow multiple processes to run without stomping on each others shared mem). it worked surprisingly well.

Sign up to request clarification or add additional context in comments.

6 Comments

So finding a way to make the Member not static and getting access to it in a different way would probably be a lot easier then? The design doesn't require the static, it just made it easier before I needed to split things up into the lib, dll, and app. If I find I absolutely can't do without the memory mapped file method I'll give that a go and let you know if I get completely lost.
@mikeschuld If the design requires no static, then ditch it and you should be good to go. trust me you'll avoid a lot of headache if you can do that. If not, you can do other things besides mmap'd images, but ultimately you're trying to share data that is, by design, replicated across every PE that uses it. And keep in mind, it isn't just the data, you actually have replicated code as well. Ideally you want this thing in its own DLL and that solves literally all your problems.
Would using a DLL instead of a static library and some use of a singleton pattern in the Lib1 DLL? Static is definitely not required if I can find another way around, it just made things a bit easier.
@mikeschuld A Lib1.dll instead of a Lib1.lib static-lib will address likely all your issues right now. It would ensure there is only one copy of any data in the global data-space (including static class members of classes) within any given single process. You can have, Dll1.dll, Dll2.dll, etc. all used by your running app.exe, and in the end the application using them all will get one Lib1.dll, its code and data, in its address space. It solves the multi-copy-of-static-lib issue you're having, but does introduce an addition DLL dependency (lib1.dll). if that works for you, you're good to go.
@mikeschuld That sounds correct. The latter (SetStaticMember()) method will work even with a static lib, but it is important to remember that even then each PE (portable executable) image (i.e. your DLL's and your App) all still have their own static member, so each must call this, and they still have their own copy of the code itself. using a DLL instead takes all of that away. The code, the static member, all reside in their own PE (the shared DLL) and life is good. I've very glad you got it up and running, though. Always nice when something finally works the way you want it. =P
|
1

You should link lib1 only with Dll1 or with App1, not both.

Now you have Base::_member defined both in your Dll1 and App1.

As you defined your Base class __dllexport/__dllimport, it uses Dll1 static member, but you din't declared Worker with any attributes, and it uses local static member.

I assume, you should specify attributes for Worker and do not link App1 with Lib1

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.