Using
Strings

 

 

Search
 

Sounds simple doesn't. What could be more basic than:

stock := 'Yahoo'.

In traditional Smalltalk a string contains the length of the string in the object header and thus allocates only that length. This approach is fine for Smalltalk itself but creates an annoyance when this string needs to be passed to an external call. For example:

WINAPI strlen: string basicAddress

In in STMT this passes a string to the C function 'string length' (strlen)  and the C function will assume that the string is null terminated.

Traditional Smalltalks need to allocate a new string with an extra null byte before passing this new string to an API call.

STMT on the other hand always allocates an extra hidden byte which contains the null character. Thus the literal above will occupy 6 bytes where byte 6 contains zero. You can demonstrate this in a couple of ways:

1. stock _sizeInBytes will return 6. Note the underscore which indicates an inlined or primitive method.

2 stock _byteAt: 6 will return zero (the value of the hidden byte). Again note the underscore as _byteAt: is inlined by the compiler.

You can thus pass STMT strings directly to a Windows API. Note the use of basicAddress above. If you have looked carefully in the image you will see that strings are automatically sent _asCinteger before being passed to an API. So you may say "Why do I need to send basicAddress to the string since _asCinteger automatically does that for me?". Good question and the answer is "it is a question of performance". Passing the string directly to the API involves a message send (_asCinteger). Passing the strings address (basicAddress) to the API internally just pushes the address on the stack prior to the API call which is a very quick operation.

STMT allows you to allocate strings in four different ways as shown in the table below.

 
Literal string e.g. string := 'My literal string'.
Initial state of bytes literal characters occupy bytes. Hidden byte set to zero
Garbage collection None (owned by method)
Allocated in the method.
Write-protected in generated executables. In general, the contents of a literal string should not be changed.
Allocated string e.g. string := String new: 9.
Number of bytes allocated 1 greater than the length
Initial state of bytes All bytes set to zero
Garbage collection Scanned and collected when references drop to zero
Allocated in object memory.
Fine for usage in instance variables. For methods, consider using localNew: to take advantage of stack speed.
Stack string e.g. string := String localNew: 9.
Number of bytes allocated 1 greater than the length
Initial state of bytes All bytes are uninitialized (i.e. contents unknown)
Garbage collection Not scanned. Removed from stack when method exits
Allocated on the stack which is as fast as you can get. Before passing this string to an external call the string must either be reset e.g. string reset which sets all bytes to zero or a zero must be placed in the last allocated byte e.g. string _byteAt: 10 put: 0
Care must be taken not to use this string outside of its scope or a protection violation will occur (since the string no longer exists on the stack). Do not try to use localNew: in a workspace for example and show the result.
Heap string e.g. string := String heapAlloc: 9.
Number of bytes allocated 1 greater than the length
Initial state of bytes All bytes set to zero
Garbage collection Not scanned. Removal must be done by user e.g. string heapFree
Allocated on the default process heap.
Very useful if the object model is static. For example if you need to load up large numbers of strings that will never need to be garbage collected or you can explicitly deallocate them (using heapFree).