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.
Related
I'm trying to understand something about HGLOBALs, because I just found out that what I thought is simply wrong.
In app A I GlobalAlloc() data (with GMEM_SHARE|GMEM_MOVABLE) and place the string "Test" in it. Now, what can I give to another application to get to that data?
I though (wrongfully!) that HGLOBALs are valid in all the processes, which is obviously wrong, because HGLOBAL is a HANDLE to the global data, and not a pointer to the global data (that's where I said "OHHHH!").
So how can I pass the HGLOBAL to another application?
Notice: I want to pass just a "pointer" to the data, not the data itself, like in the clipboard.
Thanks a lot! :-)
(This is just a very long comment as others have already explained that Win32 takes different approach to memory sharing.)
I would say that you are reading into books (or tutorials) on Windows programming which are quite old and obsolete as Win16 is virtually dead for quite some time.
16-bit Windows (3.x) didn't have the concept of memory isolation (or virtual /flat/ address space) that 32-bit (and later) Windows versions provide. Memory there used to be divided into local (to the process) and global sections, both living in the same global address space. Descriptors like HGLOBAL were used to allow memory blocks to be moved around in physical memory and still accessed correctly despite their new location in the address space (after proper fixation with LocalLock()/GlobalLock()). Win32 uses pointers instead since physical memory pages can be moved without affecting their location in the virtual address space. It still provides all of the Global* and Local* API functions for compatibility reasons but they should not be used anymore and usual heap management should be used instead (e.g. malloc() in C or the new operator in C++). Also several different kind of pointers existed on Win16 in order to reflect on the several different addressing modes available on x86 - near (same segment), far (segment:offset) and huge (normalised segment:offset). You can still see things like FARPTR in legacy Win16 code that got ported to Win32 but they are defined to be empty strings as in flat mode only near pointers are used.
Read the documentation. With the introduction of 32-bit processing, GlobalAlloc() does not actually allocate global memory anymore.
To share a memory block with another process, you could allocate the block with GlobalAlloc() and put it on the clipboard, then have the other process retreive it. Or you can allocate a block of shared memory using CreateFileMapping() and MapViewOfFile() instead.
Each process "thinks" that it owns the full memory space available on the computer. No process can "see" the memory space of another process. As such, normally, nothing a process stores can be seen by another process.
Because it can be necessary to pass information between processess, certain mechanisms exists to provide this functionality.
One approach is message passing; one process issues a message to another, for example over a pipe, or a socket, or by a Windows message.
Another is shared memory, where a given block of memory is made available to two or more processes, such that whatever one process writes can be seen by the others.
Don't be confused with GMEM_SHARE flag. It does not work the way you possibly supposed. From MSDN:
The following values are obsolete, but are provided for compatibility
with 16-bit Windows. They are ignored.
GMEM_SHARE
GMEM_SHARE flag explained by Raymond Chen:
In 16-bit Windows, the GMEM_SHARE flag controlled whether the memory
should outlive the process that allocated it.
To share memory with another process/application you instead should take a look at File Mappings: Memory-mapped files and how they work.
Sorry if this question has been answered before; however all of the questions that are similar seem to be related to global or static variables in a DLL and sharing of those.
Is it possible to have one instance of a dll shared between two separate applications?
I have two applications (appA, appB) and a DLL (theDLL).
I am seeing if it is possible for appA to call a function in theDLL which then creates a variable on the heap and stores that in theDLL. At a later time, I would like to have appB connect to theDLL and be able to access that variable created earlier. Again, sorry if this answer is the same as static and global variables in dlls.
Here is some psuedo code:
(theDLL)
class VariableHolder
{
public:
void StoreVariable(int x)
{
mInt = new int(x);
}
int GetVariable()
{
return mInt;
}
private:
int mInt;
}
(appA)
int main()
{
...
(assuming we got access to a VariableHolder singleton created in theDLL)
theVarialbeHolder.StoreVariable(5);
...
}
(appB)
int main()
{
...
(assuming we got access to a VariableHolder singleton created in theDLL)
if (theVarialbeHolder.GetVariable() == 5)
{
cout << "Hurray, how did you know?";
}
...
}
This exactly is not possible - as the address spaces for the two processes are different (because they're virtual, having been created by the kernel), so a valid pointer in one won't work within the other. However, you can use shared memory to transport raw scalar data (strings, integers) between processes - here's how.
Yes, this is possible using shared memory. It doesn't need to use a shared DLL though.
Depending on the operating, the approaches are somewhat different:
On Windows, a shared file is used on mapped into memory (see Creating Named Shared Memory).
On Linux and Unix, there are direct functions to create shared memory areas, e.g. System V IPC. Just google for it.
Shared libraries on almost any modern operating system are implemented by shared read-only executable and data pages, mapped simultaneously into the address space of any process that uses the given library. On Windows though (in contrast to most Unix system) this sharing can also be extended to read-write data segments in DLLs, so it is possible to have global variables in a DLL, shared among all images that have the DLL loaded. To achieve this, there is a two-step process involved. First you tell the compiler to put the shared variables in a new named data section:
#pragma data_seg (".myshared")
int iscalar = 0;
int iarray[10] = { 0 };
#pragma data_seg ()
It is important to have all those variables statically intialised otherwise they will end up into the .bss section instead. Then you have to tell the linker that you'd like to have the .myshared section with shared read-write attributes using the /SECTION:.myshared,RWS option.
This mechanism is much simpler than creating and binding to named shared memory objects but it only allows to share statically allocated global variables - you cannot use it to share data on the heap as the heap is private to the process. For anything more complex you should use shared memory mappings, i.e. as shown on the MSDN page, linked in the answer from H2CO3.
This is not possible. The DLL can be shared in the 2 process but the data isn't. It's the code or program image (i.e. the logic or instructions) that is shared and not the data. Every Dll is mapped into the virtual address space of the process that loads it so the data either is on the data section of the process or on stack if it is local to the function. When a process is executing the address of the other process data is not visible.
You need to do some reading on virtual memory and how memory management unit(MMU) works. The OS, CPU, MMU works together to make it possible. The reliable way to do this is inter process communication. You can use shared memory where each process has a copy of data in form of virtual address but it is eventually mapped to same location into the real memory i.e the real address. The OS makes it possible.
This as #H2CO3 pointed out, is not possible because of different address spaces.
However, from your problem, it looks like you need either a surrogate process around that DLL or a Service and then different processes can connect to that surrogate process/exe and use the shared memory.
You must use shared memory (as was written above).
I recommend to use boost interprocess library. See documentation about shared memory - Shared memory between processes
I have been looking for a way to dynamically load functions into c++ for some time now, and I think I have finally figure it out. Here is the plan:
Pass the function as a string into C++ (via a socket connection, a file, or something).
Write the string into file.
Have the C++ program compile the file and execute it. If there are any errors, catch them and return it.
Have the newly executed program with the new function pass the memory location of the function to the currently running program.
Save the location of the function to a function pointer variable (the function will always have the same return type and arguments, so
this simplifies the declaration of the pointer).
Run the new function with the function pointer.
The issue is that after step 4, I do not want to keep the new program running since if I do this very often, many running programs will suck up threads. Is there some way to close the new program, but preserve the memory location where the new function is stored? I do not want it being overwritten or made available to other programs while it is still in use.
If you guys have any suggestions for the other steps as well, that would be appreciated as well. There might be other libraries that do things similar to this, and it is fine to recommend them, but this is the approach I want to look into — if not for the accomplishment of it, then for the knowledge of knowing how to do so.
Edit: I am aware of dynamically linked libraries. This is something I am largely looking into to gain a better understanding of how things work in C++.
I can't see how this can work. When you run the new program it'll be a separate process and so any addresses in its process space have no meaning in the original process.
And not just that, but the code you want to call doesn't even exist in the original process, so there's no way to call it in the original process.
As Nick says in his answer, you need either a DLL/shared library or you have to set up some form of interprocess communication so the original process can send data to the new process to be operated on by the function in question and then sent back to the original process.
How about a Dynamic Link Library?
These can be linked/unlinked/replaced at runtime.
Or, if you really want to communicated between processes, you could use a named pipe.
edit- you can also create named shared memory.
for the step 4. we can't directly pass the memory location(address) from one process to another process because the two process use the different virtual memory space. One process can't use memory in other process.
So you need create a shared memory through two processes. and copy your function to this memory, then you can close the newly process.
for shared memory, if in windows, looks Creating Named Shared Memory
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366551(v=vs.85).aspx
after that, you still create another memory space to copy function to it again.
The idea is that the normal memory allocated only has read/write properties, if execute the programmer on it, the CPU will generate the exception.
So, if in windows, you need use VirtualAlloc to allocate the memory with the flag,PAGE_EXECUTE_READWRITE (http://msdn.microsoft.com/en-us/library/windows/desktop/aa366887(v=vs.85).aspx)
void* address = NULL;
address= VirtualAlloc(NULL,
sizeof(emitcode),
MEM_COMMIT|MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
After copy the function to address, you can call the function in address, but need be very careful to keep the stack balance.
Dynamic library are best suited for your problem. Also forget about launching a different process, it's another problem by itself, but in addition to the post above, provided that you did the virtual alloc correctly, just call your function within the same "loadder", then you shouldn't have to worry since you will be running the same RAM size bound stack.
The real problems are:
1 - Compiling the function you want to load, offline from the main program.
2 - Extract the relevant code from the binary produced by the compiler.
3 - Load the string.
1 and 2 require deep understanding of the entire compiler suite, including compiler flag options, linker, etc ... not just the IDE's push buttons ...
If you are OK, with 1 and 2, you should know why using a std::string or anything but pure char *, is an harmfull.
I could continue the entire story but it definitely deserve it's book, since this is Hacker/Cracker way of doing things I strongly recommand to the normal user the use of dynamic library, this is why they exists.
Usually we call this code injection ...
Basically it is forbidden by any modern operating system to access something for exceution after the initial loading has been done for sake of security, so we must fall back to OS wide validated dynamic libraries.
That's said, one you have valid compiled code, if you realy want to achieve that effect you must load your function into memory then define it as executable ( clear the NX bit ) in a system specific way.
But let's be clear, your function must be code position independant and you have no help from the dynamic linker in order to resolve symbol ... that's the hard part of the job.
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.
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.