How to obtain the address of a string variable?

Just starting out? Need help? Post your questions and find answers here.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Re: How to obtain the address of a string variable?

Post by Trond »

Libprocedure(inparameters1, inparameter2, ..., AddressOf(myStringVariable))
Because the dll has its own string heap, this is not guaranteed to work even if you could get the address of myStringVariable, which is why you shouldn't.
Marlin
Enthusiast
Enthusiast
Posts: 406
Joined: Sun Sep 17, 2006 1:24 pm
Location: Germany

Re: How to obtain the address of a string variable?

Post by Marlin »

This extra string heap thing, seems to be a fairy tale.

I tested it and compared the addresses of the created string data
with other string data created without the help of the library:

-> They are in the same memory area,

practically touching each other front and back.

I testet the memory behaviour
assigning the same string data via string literal one time
via library call another time and found the same behaviour.
(Testet with my linux system yet.)

Why should this use another string heap?
After all it is not another process creating the strings,
but only code stored in another file.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Re: How to obtain the address of a string variable?

Post by Trond »

The different heap stuff is on Windows, on Linux I don't know. Experience shows you can free memory from the wrong heap on Windows, but it's not legal.
Why should this use another string heap?
Let's put it this way: How would the dll find the string heap of the main program? Answer: It can't, because the main program may not even be a PB program, so the dll can't even assume the main program uses a separate string heap.

When you test stuff and it works, that does not mean it's correct and will always work in the future.
Marlin
Enthusiast
Enthusiast
Posts: 406
Joined: Sun Sep 17, 2006 1:24 pm
Location: Germany

Re: How to obtain the address of a string variable?

Post by Marlin »

Testing with W2k:

-> something is different!

After assigning a string via DLL,
I find that this string data are at another location
(say 32 M instead of 8 M)

-> AND: Now newly assigned strings (no DLL used) are
also put in the new area!

This seems to apply to any strings requiring a new location,
but not to the ones that can be expanded in the old area
and therefore need no relocating.

This does not only indicate to me, that your "another heap theory"
could apply to the windows version,
but I would also speculate there is a relation to your dll string memory leak bug
and it might be related to this.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Re: How to obtain the address of a string variable?

Post by Trond »

This does not only indicate to me, that your "another heap theory"
could apply to the windows version,
I don't know where you got the idea that I speculate and guess about things. When I say the dll has its own string heap, I say that because that's the way it is.

Code: Select all

; compile to messagebox.dll
Global StringHeap

ProcedureDLL DllMain()
  !EXTRN _PB_StringHeap
  !mov eax, [_PB_StringHeap]
  !mov [v_StringHeap], eax
  MessageRequester("Dll string heap", Str(StringHeap))
EndProcedure

Code: Select all

; save to same directory and messagebox.dll and run
!EXTRN _PB_StringHeap
!mov eax, [_PB_StringHeap]
!mov [v_StringHeap], eax
MessageRequester("Main string heap", Str(StringHeap))

OpenLibrary(0, "messagebox.dll")
f = GetFunction(0, "DllMain")
CallFunctionFast(f)
CloseLibrary(0)
The memory is freed using HeapFree_(), which takes the handle to the heap as the first argument. If you give it the wrong heap handle, it is not guaranteed to work. Yes, in practice Windows is very forgiving and it will work on current versions. What are you planning to do when your whole program relies on this malfunction if it is suddenly corrected in a new Windows version?
Marlin
Enthusiast
Enthusiast
Posts: 406
Joined: Sun Sep 17, 2006 1:24 pm
Location: Germany

Re: How to obtain the address of a string variable?

Post by Marlin »

Thanks for your code Trond.
I tried to use it with linux, but got a linker error:

Code: Select all

...: undefined reference to '_PB_StringHeap' ...
So I assume this not applicable to linux in that way.

As I see it, new Windows versions may break your old code anyways.

You can only guess, how the conditions may be in the future.

When you know, how the conditions factually are,
you can adapt to them in a workable way (if at all possible).

I admit, that you should prepare for probable possibilities,
but this is also a matter of what your choices are
and how expensive each one is...

The only real alternative, I see (except for not having the procedure in a different library at all ...),
is something like Demivec suggested or maybe letting the caller create a buffer,
that the called procedure then can fill.
All the "alternatives", I could think of as yet, look kind of disadvantageous and clumbsy to me.

Besides, I'm using the linux version most of the time. ;-)

The code can and will be changed, as long as it is used,
if something is not good enough it will be made better (if possible).
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Re: How to obtain the address of a string variable?

Post by Trond »

Assume you don't care about heaps and just want nice, readable and typable code, have you considered this? Multiple threads can call any procedure at any time and it should work as long as threadsafe is enabled.

Code: Select all

;- In library:
Procedure ReturnString(String.s)
  *M = AllocateMemory(Len(String))
  PokeS(*M, String)
  ProcedureReturn *M
EndProcedure

ProcedureDLL LibraryProcedure(id)
  A.s = "asdf sdf asdfoq " + Str(id)
  ProcedureReturn ReturnString(A + "! (you can even use a string expression)")
EndProcedure

;- In main program:
Procedure.s ReceiveString(*M)
  S.s = PeekS(*M)
  FreeMemory(*M)
  ProcedureReturn S
EndProcedure

A.s = ReceiveString(LibraryProcedure(123))
Debug A
User avatar
Demivec
Addict
Addict
Posts: 4260
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: How to obtain the address of a string variable?

Post by Demivec »

Trond wrote:Assume you don't care about heaps and just want nice, readable and typable code, have you considered this? Multiple threads can call any procedure at any time and it should work as long as threadsafe is enabled.
Just a reminder, you would need to make some adjustments to the AllocateMemory() if unicode is used. You would also need to include memory for the Null.

Code: Select all

Procedure ReturnString(String.s)
  *M = AllocateMemory((Len(String) + 1) * SizeOf(Character))
  PokeS(*M, String)
  ProcedureReturn *M
EndProcedure
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Re: How to obtain the address of a string variable?

Post by Trond »

Right, I forgot.
Marlin
Enthusiast
Enthusiast
Posts: 406
Joined: Sun Sep 17, 2006 1:24 pm
Location: Germany

Re: How to obtain the address of a string variable?

Post by Marlin »

Thank you Trond and Demivec.

This seems workable,
but wouldn't the called library allocate the memory in its heap
and the memory the be freed by the caller side,
similar to my string approach?

What I like less about this approach is, that it requires some copying of strings.
I would like to avoid creation of additional strings and copying of them as
much as possible.

Once I had an application, that performed very slow in some circumstances.
I traced it to repeated string manipulations that probably went slow
when it required some kind of garbage collection.
Then I replaced the string handling by an approach with (reusable) memory buffers
and the application performed serveral orders of magnitude faster.
Marlin
Enthusiast
Enthusiast
Posts: 406
Joined: Sun Sep 17, 2006 1:24 pm
Location: Germany

Re: How to obtain the address of a string variable?

Post by Marlin »

I added an "Edit for future visitors" in my entry post above,
to show a way I found to get the address of a string variable
into a pointer.
Post Reply