1

i've created dll and implemented shared memory that every connected process can use. My problem is that i can't change anything in object, which is stored in the memory.

my class :

class MyClass
{
public:
    MyClass();
    void test();
    int counter;
};

void MyClass::test() {
    MessageBoxA(NULL, "test", "test", 0x0000000L);
    counter++;
}

in stdafx.h i have :

static offset_ptr<MyClass> offset_mt;
static managed_shared_memory *memSegment;

I initialize shared memory and pointer :

memSegment = new managed_shared_memory(create_only, SHARED_MEMORY_NAME, 4096);
offset_mt = memSegment->construct<MyClass>("MyClass myClass")();

And then in an exported function i call

offset_mt.get()->test();

Im calling this from Java using JNA and result is a memory error (Invalid memory access). However, if I delete 'counter++' from test method, everything works fine - message box appears. Is there a limitation that I cant modify objects inside mapped memory or is this done the other way?

  • To eliminate any JNA quirks (not initializing CRT or something), consider testing with native executable that imports your dll and calls the function. Also consider not using statics. – Eugene Aug 21 '14 at 22:35
  • Especially statics in precompiled header: in best case you'll get linker errors, in worst you'll get each compile unit getting its own copy of the variable. – Eugene Aug 21 '14 at 22:36

2 Answers2

0

Well, i solved this by moving my variables to stdafx.cpp :

offset_ptr<MyClass> offset_mt;
managed_shared_memory *memSegment;

and making them extern in stdafx.h :

extern offset_ptr<MyClass> offset_mt;
extern managed_shared_memory *memSegment;

Now it's running fine, but I've done this kinda accidentally and I'm not pretty sure why this works and previous way not. If anyone could explain this to me, it would be great.

0

When you say

static offset_ptr<MyClass> offset_mt;

compiler has to do a few things. One of them is allocating space for your variable (see where static variables are stored). Another one is calling any nontrivial constructors. This last part is done by CRT, before main() (or dllmain) runs. In fact CRT replaces your entry point and initializes statics before calling your [dll]main().

When you say that in a header, compiler is allocating space for the variable in each compilation unit that includes the header.

When you say that in stdafx.h, that means every cpp file. Normally that should result in a linker error, but sometimes it slips through (one way to do it is to use anonymous namespace) and results in different cpp files seeing different copies of the variable. So if you are initializing in one cpp, and you using it in another, you blow up.

When you are importing the dll in interesting ways sometimes importing code doesn't call the entry point at all -- this kills most CRT facilities and results in your own statics being uninitialized. Don't know about JNA, but some old versions of .Net had this problem.

There is also static initialization fiasco, but that might not affect your particular case.

By moving your definitions into cpp and removing static modifier, you avoided all those pitfalls.

Community
  • 1
  • 1
Eugene
  • 7,180
  • 1
  • 29
  • 36