This is probably the most common problem encountered by people who are used to languages like BASIC.
Strings, lists, arrays and objects cannot be initialised using an assignment statement: data must be copied.
Unlike BASIC, this kind of data is represented by a pointer (see 9.2
PTR Type), so only the pointer would be copied by an assignment statement, not the data it points to.
The following examples all copy a pointer rather than the data, and so the memory for the data is shared (and this is probably not what was intended).
DEF s:STRING, t:STRING, l:LIST, m:LIST, x:myobj, y:myobj, a:ARRAY OF INT, b:ARRAY OF INT /* You probably don't want to do any of these */ s:='Some text in a string' l:=[-6,4,-9] x:=[1,2,3]:myobj a:=[1,-3,8,7]:INT t:=s m:=l y:=x b:=a
All the declarations allocate memory for the appropriate data.
The first four assignments replace the pointers to this memory with pointers to some statically allocated memory.
The memory allocated by the declarations is probably now unreachable, because the only pointers to it have been over-written.
BASIC programmers might expect, say, the assignment to
s to have copied the string into the memory allocated for
s by its declaration, but this is not the case (only the pointer to the string is copied).
For the E-string,
s, and E-list,
l, there is another, disastrous side-effect.
The assignment to
s, for example, means that
s will point to a normal string, not an E-string.
s can no longer be used with any of the E-string functions.
The same considerations apply to the E-list,
l, as well.
The final four assignments also copy only the pointers.
This means that
t will point to exactly the same memory.
So they will represent exactly the same string, and any change to one of them (by a
StrAdd, for example) will appear to change both (of course, only one lump of memory is being changed, but there are two references to it).
This is called memory sharing, and is only a problem if you didn't intend to do it!
To get the result that a BASIC programmer might have intended you need to copy the appropriate data.
For E-strings and E-lists the functions to use are, respectively,
All other data must be copied using a function like
CopyMem (an Amiga system function from the Exec library).
(Normal strings can be copied using
AstrCopy built-in function, see the Reference Manual.)
Here's the revised forms of the above assignments:
DEF s:STRING, t:STRING, l:LIST, m:LIST, x:myobj, y:myobj, a:ARRAY OF INT, b:ARRAY OF INT StrCopy(s, 'Some text in a string') /* Defaults to ALL */ ListCopy(l, [-6,4,-9]) /* Defaults to ALL */ CopyMem([1,2,3]:myobj, x, SIZEOF myobj) CopyMem([1,-3,8,7]:INT, a, 4*SIZEOF INT) StrCopy(t, s) /* Defaults to ALL */ ListCopy(m, l) /* Defaults to ALL */ CopyMem(x, y, SIZEOF myobj) CopyMem(a, b, 4*SIZEOF INT)
Notice that you need to supply the size (in bytes) of the data being copied when you use
The parameters are also given in a slightly different order to the E-string and E-list copying functions (i.e., the source must be the first parameter and the destination the second).
CopyMem function does a byte-by-byte copy, something like this:
PROC copymem(src, dest, size) DEF i FOR i:=1 TO size DO dest++:=src++ ENDPROC
Of course, you can use string constants and lists to give initialised arrays, but in this case you should be initialising an appropriately typed pointer. You must also be careful not to run into a static data problem (see 9.5.7 Static data).
DEF s:PTR TO CHAR, l:PTR TO LONG, x:PTR TO myobj, a:PTR TO INT s:='Some text in a string' l:=[-6,4,-9] x:=[1,2,3]:myobj a:=[1,-3,8,7]:INT
Go to the Next or Previous section, the Detailed Contents, or the Amiga E Encyclopedia.