Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations John Tel on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How do I reset a user-defined data type 1

Status
Not open for further replies.

AndyGroom

Programmer
May 23, 2001
972
GB
Hi,

I have a complicated user-defined data type which includes numerous arrays, different variable types and so on, and I want to reset (erase) it so that all the numbers are back as 0, all the strings back as "" and so on.

I know I can do it like this:

Dim A as MyDataType
Dim B as MyDataType

' (Code here that populates variable A)

A = B

' (This resets A back to empty because B is empty)

However, my application is large and VB is unhappy with holding two of these variables in the same routine, in effect I can't spare the space to have an empty variable for resetting purposes.

VB doesn't allow Erase with a user-defined type, and I can't do A = Nothing, is there any other way of doing what I want?

- Andy.


 
Couldn't you just make your UDT a class instead? You'll still have the . format. For example, as a UDT you would have:

MyUDT.Name

and in a class it would look the same:

( Classname is "MyUDT" )

MyUDT.Name

Then you would be able to do the = Nothing to reset it.

Of course, this will require redoing code elsewhere in your ap. Other than this, I don't know of any way of resetting it other than the way you described in your post.

Robert
 
You can define a UDT in a class module (one w/o an associated object). Then you could declare several instances
locally in each desired module. Then, whenever execution
left the module, that variable/instance would be "out-of-scope" and automatically reset to hold nothing.
You'd have to watch out for events that momentarily call for handling, these will erase your local variables to (because they'd be out-of-scope in the new event handler).

 
This is probably not a 'best' programming practice but if you declare you UDT as an array with one element then you should be able to use the Erase statement.

Dim A(0) as MyDataType

Just a thought. Thanks and Good Luck!

zemp
 
One way that you can clear a UDT to all nulls would be to use the CopyMemory API. In the public module, define the API function
Code:
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
Then in your code, when your ready to clear the function, try the following line
Code:
CopyMemory A, ByVal StrPtr(String(Len(A), Chr(0))), Len(A)
where A respresents the name of the UDT structure. Good Luck
--------------
As a circle of light increases so does the circumference of darkness around it. - Albert Einstein
 
Hi Cajun,

This works great, thanks. It isn't likely to cause a page fault or anything is it? If it helps, or is relevant, all my strings in the UDT are fixed-length.

- Andy.
 
You do have to be careful when using the CopyMemory API because you can destroy things in memory that in turn leads to unpredictable results. If you make a mistake with one of the three parameters, then yes, you can cause a page fault. I've not encountered problems with the CopyMemory once I've gotten the three parameters absolutely correct. Good Luck
--------------
As a circle of light increases so does the circumference of darkness around it. - Albert Einstein
 
Hi Cajun,

Please help!

I used your approach above and all seemed to be well. HOWEVER...! It doesn't work on UDTs with variable length strings, does it? Or does it?

I can't see how, if you think yes, since doing Len(UDT) returns the same value whether the strings are empty or whether they contain information.

Is there a Len() function that returns the length of a UDT even when it contains data? Using that would probably fix it.

- Andy.
 
Yes, there is. LenB. However, variable length strings are held in a UDT merely as a pointer. So, no matter how long your variable length string is, it still only contributes 4 bytes to the size of the UDT. On the other hand, this means that CajunCenturion's trick still works quite happily since, rather than overwriting the contents of the actual string, it merely sets a null pointer.
 
When you define a UDT with a fixed length string, then the size of the UDT includes the lenght of the string. However, if you have variable length strings in the UDT, then inside the UDT is a pointer (4 bytes) to the string. The UDT does not contain the value of the string, it contains the memory address of where string value is. So even though the length of the string may change, the size of the pointer to the string does not change, therefore, Len(UDT) does not change. Good Luck
--------------
As a circle of light increases so does the circumference of darkness around it. - Albert Einstein
 
Hi,

OK, I take all that on board. However, when I try this technique I get a memory problem on 4 different machines in 3 different OSs. I've checked all instances of CopyMemory and they're all correct in terms of using the right variable for each parameter.

It causes an exception in oleaut32 in all cases. However, I wrote a test program that does the CopyMemory 50,000 times and I don't get a problem.

Hmmm...

- Andy
 
Without know the details of how the heap is being managed, it would be tough to figure it out. I would run the same tests on the same machines, using fixed length strings. Good Luck
--------------
As a circle of light increases so does the circumference of darkness around it. - Albert Einstein
 
Hi,

I have confidence in your method, I think the complexity and size of my progam is the reason for the error - I either get the exception or Out of Memory on the CopyMemory line. If I reset each element of the UDF through code, although a hassle, it's as steady as a rock.

- Andy.
 
Final addendum...

Guys, the CopyMemory method does work but with one important exception which has caused me no end of bug-tracking!

If your UDT contains any Boolean types, they DO NOT get reset back to false (0) for some reason. Eg:

MyUDT.Toggle = True
CopyMemory {...}
?MyUDT.Toggle
True

Any idea why this would be? Surely it should get reset back to 0?

- Andy.
 
Could be because the UDT is being filled with a null character and not a numeric value of zero. A null character is not the same as the zero character.

Good catch, and is worthing looking into. Good Luck
--------------
As a circle of light increases so does the circumference of darkness around it. - Albert Einstein
 
Please let me know if you come up with a solution! Maybe copying 0's into the memory block first, then nulls straight afterwards...?

- Andy.
 
CajunCenturion
Wouldn't ZeroMemory be a better choice in this situation?

Code:
Public Declare Sub ZeroMemory Lib "KERNEL32" Alias "RtlMoveMemory"  (dest As Any, ByVal numBytes As Long)
Take Care

Matt
If at first you don't succeed, skydiving is not for you.
 
You can also use ZeroMemory function instead of CopyMemory.
It is specially designed for that purpose - i.e. for zeroing memory.

Private Declare Sub ZeroMemory Lib "kernel32" Alias "RtlMoveMemory" (dest As Any, ByVal numBytes As Long)

Dim X As MyUDT
'
'Code that fills in members of X
'
ZeroMemory X, LenB(MyUDT)

It even works on UDTs containing variable length strings and booleans. I tested it a million times using a loop.
 
ZeroMemory it is then. Named after a VIC20?

Thanks.

- Andy.
 
Hi Hypetia,

Tried using ZeroMemory in XP and it just crashes VB all the time, can you think what I'm doing wrong? I tried all the following combinations:

Dim X as MyUDT

ZeroMemory X, LenB(MyUDT)
ZeroMemory X, LenB(X)
ZeroMemory X, Len(MyUDT)
ZeroMemory X, Len(X)

...all led to immediate crashes.

- Andy.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top