FTE pointers (FTE_MEMALLOC)

To create an array of pointers.

1. Create a type of variable called a ‘floatptr’:

typedef float *floatptr; // a pointer to a float

2. Make it a .field (ie all entitites get one … BUT… ONLY the entities which need an array get memory allocated for one!)

.floatptr route_table;

3. Entity foo needs an array of 50 floats
#define ARRAY_SIZE 50
foo.route_table = memalloc(sizeof(float) * ARRAY_SIZE);

4. access the values via:
foo.route_table[i] = some_value; // make sure i doesn’t go over ARRAY_SIZE

////////////////////////////////////////////////////

<Spoike> look, pointers in fte are like strings.
<Spoike> if you read the null string then you get an empty string. therefore you’re allowed to read null pointers too
<OneManClan> every player gets (in ClientConnect) self.my_bot = memalloc(sizeof(entity) * MAX_BOTS);
<Spoike> the problem is that unless you’re reading bytes out of that pointer (which is only allowed if you cast it to a string first) then you’ll read whatever other data was there.
<Spoike> thus if you have (*(int*)0) then you’ll actually end up with 0xXXXX0000 where the capital Xs are undefined.
<Spoike> (first two bytes of the string table are always 0 – for the null string and QC’s annoying default empty string)
<Spoike> the following two bytes are pretty much anything, so have fun with that
<Spoike> probably some filename
<Spoike> so don’t depend upon it.
<Spoike> do not dereference null.
<OneManClan> when a bot is spawned, I go: self.my_bot[i] = spawn();
<OneManClan> and when a bot dies:
<OneManClan> remove(self.my_bot[i])
<Spoike> the easy way to avoid dereferencing null is to have a separate count value, so for (int i = 0; i < self.entrycount; i++) self.entry[i].whatever; is always safe, because entrycount will be 0 if its null and thus no dereference.
<Spoike> the normal way to avoid deferencing null is to check if the fucking thing is null before dereferencing it.
<Spoike> if (self.entry) self.entry[i] = whatever; <- that’s fine, if skipping the assignment is the correct thing to do
<Spoike> most of the time its the caller’s error if its null when it gets dereferenced, so you don’t need to check ALL the time, just at any point where its value might be undefined (beware the half-second rule)
<Spoike> if your array is only ever <=4 or whatever, then you might as well just define your pointer as an array in the first place
<Spoike> then the engine will automatically allocate storage for you, and the qcc will insert bounds checks for you too

///////////

Reference (fteextensions.qc):

__variant*(int size) memalloc = #384; /* Part of FTE_MEMALLOC
Allocate an arbitary block of memory */

void(__variant *ptr) memfree = #385; /* Part of FTE_MEMALLOC
Frees a block of memory that was allocated with memfree */

void(__variant *dst, __variant *src, int size) memcpy = #386; /* Part of FTE_MEMALLOC
Copys memory from one location to another */

void(__variant *dst, int val, int size) memfill8 = #387; /* Part of FTE_MEMALLOC
Sets an entire block of memory to a specified value. Pretty much always 0. */

__variant(__variant *dst, float ofs) memgetval = #388; /*
Looks up the 32bit value stored at a pointer-with-offset. */

void(__variant *dst, float ofs, __variant val) memsetval = #389; /*
Changes the 32bit value stored at the specified pointer-with-offset. */

__variant*(__variant *base, float ofs) memptradd = #390; /*
Perform some pointer maths. Woo. */

float(string s) memstrsize = #0/*:memstrsize*/; /*
strlen, except ignores utf-8 */

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>