News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

DLL Memory

Started by msmith, June 27, 2006, 04:28:10 AM

Previous topic - Next topic

msmith

I have looked at a lot of examples of DLL's using memory and noticed that most request heap memory.

Can DLL's also declare and use initialized and uninitialized memory just like an EXE?

If so, it would seem that the memory would be local to the DLL (cannot be accessed from other DLL's or a calling EXE except by getting a pointer through a function).

It looks like the answer is yes, but I would like a confirmation of this.

hutch--

A DLL can do more or less anything that an EXE can in terms of what code and data it can call or use. Where you can have difficulties is passing allocated memory addresses between an exe and DLL. You can allocate in an EXE and pass that address, make an empty handle and pass that so the DLL does the allocation etc ...

Something you can do with a DLL is produce a procedure in it that passes back the address of data in the data or data? sections to the calling exe but you need to be aware that the addresses are only valid for the time te DLL is loaded.

About the only place you can get into trouble is with stack memory in a DLL that only exists for the duration of the procedure being run.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

msmith


zooba

Also, if a DLL allocates memory in the heap returned by GetProcessHeap, the address is valid as long as the process (ie. the EXE, not the module/DLL) is running.

However, I still believe it's best practice to pass already allocated memory to a library wherever possible.

Cheers,

Zooba :U

P1

Quote from: msmith on June 27, 2006, 04:28:10 AMCan DLL's also declare and use initialized and uninitialized memory just like an EXE?
Do be sure to make it's thread safe code, especially if it's going to be use concurrently.

If you don't, have fun debugging those errors in logic.  Because it will compile and most of the time work, until loaded up.

Regards,  P1  :8)

msmith

Thanks to all of you for your help.

The particular DLL I was asking about was one created by my compiler for control creation.

Your answers were of particular interest to me because I need to do more than one type of memory in a given control. For example, I need a separate copy of certain items (propeties) for each instance of the control and certain static variables for the class.

Thank you all again.

Mike

zooba

The way I implemented what you're looking at is through a pointer stored in GWL_USERDATA which pointed to the instance data. The first value was a pointer to the class data.

So to get the instance data:

invoke GetWindowLong, hWnd, GWL_USERDATA
ASSUME eax:PTR INSTANCE_DATA


And the class data:

invoke GetWindowLong, hWnd, GWL_USERDATA
mov    eax, [eax]
ASSUME eax:PTR CLASS_DATA


Though you'd probably want to move EAX into another register first so you can keep using it. I just wrote these quickly off the top of my head :wink

Cheers,

Zooba :U

msmith

zooba,

Thanks for the tip.

I am already doing something similar, but my compiler (as do most, if not all) tends to use static memory rather than registers. This is mostly because the compiler does not know which registers will be overwritten in the next high level statement.

Therefore, the data pointer is stored in the cbWndExtra of the hwnd (GM_USERDATA should be left for the application to use) and then put into a special structure my compiler uses called a vector. A vector is like a reference in c++ if you're familiar with that. Another way to look at a vector is to think of it as a based variable in which the user effectively decides where a variable will reside. Still another way to think of a vector is that it is a pointer with no need for pointer notation when dereferencing. Once the vector is set, the variable (in this case a complex structure) is referenced by the user exactly as if it were a static variable.

I really do appreciate your tip because it confirms to me that I am on the right track. All of the heap allocation and deallcation is done behind the scenes for the user in the WM_CREATE and WM_DESTROY events.

Mike

Here is the code we are talking about (in FASM):


; Control DLL
align 4
proc !DllEntryPoint, hinstDLL,fdwReason,lpvReserved
enter
mov eax,[hinstDLL]
mov [hInstance],eax
mov [!ControlClass.hInstance],eax
mov [!ControlClass.hIcon],0
invoke LoadCursor,0,IDC_ARROW
mov [!ControlClass.hCursor],eax
mov [!ControlClass.style],0
mov [!ControlClass.lpfnWndProc],!ControlProc
mov [!ControlClass.cbClsExtra],0
mov [!ControlClass.cbWndExtra],4
mov [!ControlClass.hbrBackground],0
mov [!ControlClass.lpszMenuName],0
mov [!ControlClass.lpszClassName],!ControlClassName
invoke RegisterClass,!ControlClass
mov eax,TRUE
endp

proc !ControlProc,!hwnd,wmsg,wparam,lparam
enter
push ebx esi edi
mov [!PassEvent],0
mov ebx,[wmsg]
cmp ebx,WM_CREATE
jne !Notwmcreate
invoke GetProcessHeap
invoke HeapAlloc,eax,HEAP_ZERO_MEMORY,[ControlData+4]
invoke SetWindowLong,[!hwnd],0,eax
jmp !ProcessMsg
!Notwmcreate:
invoke GetWindowLong,[!hwnd],0
mov [ControlData],eax
cmp ebx,WM_DESTROY
jne !ProcessMsg
invoke GetProcessHeap
invoke HeapFree,eax,NULL,ebx
!ProcessMsg:
call ProcessMsg
cmp [!PassEvent],0
jne !DefWndProc
xor eax,eax
jmp !Finish
!DefWndProc:
invoke DefWindowProc,[!hwnd],[wmsg],[wparam],[lparam]
!Finish:
pop edi esi ebx
endp


"ProcessMsg" is a predefined user subroutine in which the user can process events. If the user does not wish to process a particular event, a PassEvent statement is executed which sets [!PassEvent] to a non-zero value.

zooba

The reason I didn't use cbWindowExtra is because I was using it for standard controls, some of which use cbWindowExtra already. To use it consistently I would've needed to make all of them large enough so that the offset was the same and wouldn't overwrite any of the control's own data.

I just put a big disclaimer somewhere saying "don't use GWL_USERDATA with these controls!" :bg

Cheers,

Zooba

dougiem

I have not been into the forum for a while _ scary_
this is the second docket with the same reply,
http://doc.ddart.net/asm/Microsoft_MASM_Programmers_Guide_v6.1/Chap_10.htm
shows the doos and donts  - and stack allocation etc - a good article