Suppose you have a VB6 app which uses a C++ DLL. They share the same memory (you can use pointers from one in the other). The DLL is declared in the VB6 app with Public Declare Function ... Lib ...
So how does this fit with the "Stack grows from one side of memory, heap from the other" philosophy? Where is the stack of the DLL? Are global DLL variables allocated when the application is started? If so, why does it only give me an error when I try to run a function from the DLL?
VB6 uses thread local storage for module-level variables, not data segements. What this means is that public (global) variables in a module can have different values per different threads. Which is not what a C/C++ developer is used to.
Global variables are stored in the Data Segment.
http://en.wikipedia.org/wiki/Data_segment
The stack is only used for local variables.
Global DDL symbols will be in the DLL image itself. If the DLL uses the symbol as a pointer to which it attaches some dynamic memory, then the memory will be from whatever the dynamic allocation is from (typically the heap used by the CRT). We would need to see exactly how the VB declaration of the C++ import looks like and what the C++ DLL does (could be initializing on DllMain, could be a static region in the DLL image, could require call to some Init functione etc etc etc).
"Stack grows from one side of memory, heap from the other" was true maybe on 8088 processors, no such thing happens on modern platforms. Stack gets allocated per thread and goes upwards, true, but there could be hundreds of stacks in a process. Heap gets allocated all over the place and grows, basically, at random. And a typical process also has several heaps in it.
There is typically one stack per thread. The function in the DLL will use the stack of the current thread (the thread on which is was invoked).
See Remus's answer to your other questions about memory management.
Related
I have two console applications A1.exe A2.exe and one DLL. Both run in debug mode, optmization turned off.
There is global const char* variable which I export from this dll and import back in A1 and A2:
//dll.h
extern "C" {DLLEXPORT extern const char* str;}
//dll.cpp
const char *str = "qwerty123";
I expect "qwerty123" to be created in read-only section of DLL and I expect that memory manager of Windows will map real memory with this string to some virtual memory address of A1.exe and different virtual address of A2.exe and do not create real copy of data. I expect that to happen also for all function definitions from that dll.
I run both applications at the same time and they both print correct strings imported from DLL. However I want some proof so I brutally use Cheat Engine to attach to A1.exe process and change that read-only string to some different value. Result is that A1.exe prints new value and A2.exe still prints old value. How to explain this?
1. I thought it is read-only memory and it will be shared to save real memory so why value changed only for one application?
2. How can I get proof that sections with program code (exported functions) are not duplicated for both processes?
The optimization you are thinking about here is called copy on write. In the case of Visual C++ all global variables defined in a DLL are initially loaded in shared memory pages with the PAGE_WRITECOPY attribute. If some process writes into such a location it receives its own page with PAGE_READWRITE attribute and uses it further on. Visual C++ seems to make no difference between const and non const global variables as that property is a compiler feature. For instance it can be thrown away with a cast and handling it from the OS perspective would be a headache and a security hole as well.
Try searching web for PAGE_WRITECOPY to learn more details.
The concept of 'read-only memory' is largely inapplicable to this discussion. Yes, the operating system has ways of making certain areas of memory appear as read-only to your program, but a) this memory is perfectly real just as any other memory, and b) your string literal is not being stored into any such memory anyway.
When you declare a string as const you are only preventing yourself from changing it from within your C++ program, and you might also be enabling some compiler optimizations, though as you have correctly turned them off while troubleshooting, they do not play any role in this discussion. To prove what I am talking about, you can cast-away the constness of that char* pointer, and then you can perfectly well modify the string pointed by it.
Each instance of the DLL has its very own data segment. DLL instances do not share their data. So, of course when you modify the item, you are only modifying it in the data segment of one instance of the DLL, while the data segment of the other DLL instance remains unchanged.
In order to share data you would need to use VirtualAllocEx() and WriteProcessMemory(), or better yet CreateFileMapping() and MapViewOfFile[Ex](), or some other mechanism.
The value of a 'read-only global variable' of a DLL may be different for processes which attach the DLL. Thus, it is unsafe if the DLL shares the single physical memory of a 'read-only global variable' for several processes. The cautious but safe solution is to create differenct physical memory instances of a 'read-only global variable' for several processes.
For example, in the dll.cpp,
int foo(){return 1;}
typedef int (*C_pFunc)();
const C_pFunc pf=foo;
Obviously, A.exe and B.exe both load the dll, function foo() in the DLL may have different logical addresses in A.exe and B.exe. Therefore, the global const variable pf may have different initialized values in A.exe and B.exe.
This is a typical phenomenan for COM dll, when the COM dll is attached to a process, many vtables as global const variables should be initialized with the function logical addresses in this process.
I have a hypothesis here, but it's a little tough to verify.
Is there a unique stack frame for each calling thread when two threads invoke the same method of the same object instance? In a compiled binary, I understand a class to be a static code section filled with function definitions in memory and the only difference between different objects is the this pointer which is passed beneath the hood.
But therefore the thread calling it must have its own stack frame, or else two threads trying to access the same member function of the same object instance, would be corrupting one another's local variables.
Just to reiterate here, I'm not referring to whether or not two threads can corrupt the objects data by both modifying this at the same time, I'm well aware of that. I'm more getting at whether or not, in the case that two threads enter the same method of the same instance at the same time, whether or not the local variables of that context are the same places in memory. Again, my assumption is that they are not.
You are correct. Each thread makes use of its own stack and each stack makes local variables distinct between threads.
This is not specific to C++ though. It's just the way processors function. (That is in modern processors, some older processors had only one stack, like the 6502 that had only 256 bytes of stack and no real capability to run threads...)
Objects may be on the stack and shared between threads and thus you can end up modifying the same object on another thread stack. But that's only if you share that specific pointer.
you are right that different threads have unique stacks. That is not a feature of c++ or cpp but something provided by the OS. class objects won't necessary be different. This depends on how they are allocated. Different threads could share heap objects which might lead to concurrent problem.
Local variables of any function or class method are stored in each own stack (actually place in thread's stack, stack frame), so it is doesn't matter from what thread you're calling method - it will use it's own stack during execution for each call
a little different explanation: each method call creates its own stack (or better stack frame)
NOTE: static variables will be the same
of course there exists techniques to get access to another's method's stack memory during execution, but there are kinda hacks
Suppose I have shared library with this function where "i" is some global variable.
int foo() {
return i++;
}
When I call this function from multiple processes the value of "i" in each process is independent on the other processes.
This behavior is quite expected.
I was just wondering how is usually this behavior implemented by the linker? From my understanding the code is shared between processes, so the variable has to have the same virtual address in all address spaces of every program that uses this library. That condition seems quite difficult to accomplish to me so I guess I am missing something here and it is done differently.
Can I get some more detailed info on this subject?
The dynamic linking process at run time (much the same as the static linking process), allocates separate data (and bss) segments for each process, and maps those into the process address space. Only the text segments are shared between processes. This way, each process gets its own copy of static data.
the code is shared between processes, so the variable has to have the
same virtual address in all address spaces of every program that uses
this library
The code is not shared the way you think. Yes the dynamic shared object is loaded only once but the memory references or the stack or the heap that code in the so uses is not shared. Only the section that contains the code is shared.
Each process has it's own unique address space, so when a process access the variable it can have different values then the other process. If the process should share the same memory, they would have to specifically set this up. A shared library is not enough for that.
I have a huge program (A) which uses about 30 (most of my own, some 3rd party) dll´s. It uses ActiveX, ATL and MFC to do different stuff. Now i want to use wxWidgets for some special tasks and will call the wxWidgets dialogs from within the program. I can do this with a special designed DLL which takes the wxW.. parts. But to run the special tasks with or without the A programm i would to like to put the wxW.. stuff in an exe (B) and these exe should address the same data from the A program. As far as i know each *.exe has its own process and so i can not share the same pointer address.
I can put in some shared data block in one of the DLLs.
#pragma data_seg("SHARED")
CClassA *g_ClassAPointer=NULL;
#pragma data_seg()
#pragma comment(linker, "/section:SHARED,RWS")
If the A is running and starts B, i can get the pointer g_ClassAPointer with the address within A. Is there a way to get the address or get an offset to reach this address within B ?
Thanks in advance,
Howie
BTW: We also want to use wxWidgets to fade all the MFC stuff more and more to cross platform code otherwise i would stick to MFC or use the wxW - DLL within a wrapper *.exe.
You're looking for shared memory, and the usual way to create that is via CreateFileMapping. This can create shared memory backed by a named file, or backed by the paging file. (Memory allocated by GlobalAlloc is also backed by the paging file, so that's no unusual thing).
In either case, the memory block from CreateFileMapping is named, so another process can access the shared memory block by calling OpenFileMapping with the same name.
Keep in mind that the shared memory block might reside at different offsets in memory. Also, if you put CClassA in shared memory, there's no automatic mechanism to ensure that all pointers inside CClassA point to the same shared memory block. E.g. putting a std::string or MFC CString in shared memory is unlikely to achieve what you intended.
If I have a global variable defined in a DLL that my application load, is this variable is located at the same memory region that my others global variable defined in my application (so not directly in the DLL) ?
Global data loaded as part of the EXE and global data loaded as part of the DLL both reside in the virtual memory space of the same process, though in different areas corresponding to the segments defined in those EXE and DLL files. Since they are in the same virtual memory space, code in the DLL can use a pointer to an EXE global that the EXE passes to it, and vice-versa.
The answer is yes.
MSDN quote:
"Every process that loads the DLL maps it into its virtual address space".
Go to this link and you'll find the answer to your doubt.
Good luck
Your tag indicates C++ but the answer may also be platform/OS dependent. Under windows each process will make a copy of the data. Here's a snippet from the MSDN Run Time Behavior article:
Each time a new process attempts to
use the DLL, the operating system
creates a separate copy of the DLL's
data: this is called process attach.
In a single process global data is well,... global.