Accessing a low address in RAM is called 'zero page addressing'. Usually you're note allowed to do this, because this is privvy to the O/S only. It doesn't like people dinking in it's space.
I've reformatted your code slightly, removed a couple of your pointer typedefs and added them into the struct typedef's (thank you for using 'typedef' by the way) and I changed the last field in the Question structure to eliminate the explicit '*' and take advantage of the ListNodePtr var (with the implicit '*'), instead.
Code:
#include <PalmOS.h>
typedef struct node
{
char* data;
int dest;
struct node* next;
}ListNode,*ListNodePtr;
typedef struct
{
int number;
char* question;
int type;
ListNodePtr answers;
}Question,*QuestionPtr;
void InsertAnswer(Question* q, char* data, int dest)
{
ListNodePtr newNode;
MemHandle listHandle = MemHandleNew(sizeof(ListNode));
newNode = (ListNodePtr)MemHandleLock(listHandle);
newNode = q->answers;
while(HasNext(newNode) == 1)
newNode = GetNext(newNode);
newNode->data = data;
newNode->dest = dest;
newNode->next = NULL;
}
int HasNext(ListNodePtr node)
{
if(node->next != NULL)
return 1;
else
return 0;
}
ListNodePtr GetNext(ListNodePtr node)
{
if(HasNext(node) == 1)
return node->next;
else
return NULL;
}
First of all-- don't do this:
MemHandle listHandle = MemHandleNew(sizeof(ListNode));
You failed to check for any memory errors-- What if listHandle never gets allocated? If not, it is holding a junk value (at best a zero) that could point to anywhere in RAM.
Also, as a matter of habit, try initializing all pointers to zero prior to using or allocating them. This way they are at a 'known' state, and you can easily check for it.
Furthermore, you don't check for pointer validity on entry to InsertAnswer(), either. You should always check to see if passed pointers are valid:
Code:
void InsertAnswer(Question* q, char* data, int dest)
{
ListNodePtr newNode = nil; /* declare AND initialize to zero */
if(!q) /* pointer a zero? */
bail;
if(!data)
bail;
...
You also create your handle to your list (listHandle) and lock it down, but you never unlock it. You also don't check to see if newNode is valid after you lock and dereference.
Because you are looking for a zero or positive result-- not specifically a 1 or a single zero, you don't have to waste code using == or !=. In fact, you can do away with HasNext() and GetNext() altogether. It's much more effecient to put them inline, within InsertAnswer(), like so:
Code:
void InsertAnswer(Question* q, char* data, int dest)
{
ListNodePtr newNode;
MemHandle listHandle = NULL;
listHandle = MemHandleNew(sizeof(ListNode));
if(listHandle)
{
newNode = (ListNodePtr)MemHandleLock(listHandle);
newNode = q->answers; /* whoops--> pointer screwup here */
if(newNode) /* is this pointer valid? */
{
while(newNode->next) /* walk the link list */
newNode = newNode->next;
newNode->data = data; /* stomp on link's data */
newNode->dest = dest;
newNode->next = NULL;
};
};
}
Okay, let's step back and look at just exactly what InsertAnswer() does. If we flowchart it and look at it, it does this:
Code:
InsertAnswer
{
Allocate ListHandle datablock
Lock ListHandle Down and Dereference it
(newNode becomes the master pointer to the ListHandle
data block that we allocated)
Destroy value in NewNode by changing it to: q->Answers.
Zip through 'q' linked list, no longer working with our
own listHandle list, search for last valid node in
'q' linked list.
Overwrite values 'data', and 'dest' in the last 'q' node
with passed arguments.
}
Now that you know where the problems are, it's simple to rewrite it correctly.