Thread: Reading from Low Memory Error...

  1. #1
    Unregistered
    Guest

    Question Reading from Low Memory Error...

    While this may be an API specific problem, I think it is based most in my somewhat limited experience with pointers. Because I'm used to Java, which takes care of the mess of pointers for you, coming back to C (which I have used several times before) is tough.

    I'm writing some stuff for the PalmOS, and at the moment I am attempting to implement a linked list. My code compiles fine, but when run on a Palm device, I get a "Your program has just attempted to read from low memory, a technique not allowed on PalmOS". I'm not exactly sure what this means, but I have figured out the first line in my code where it occurs:

    Code:
    #include <PalmOS.h>
    
    typedef struct node
    {
    	char* data;
    	int dest;
    	struct node* next;
    } ListNode;
    
    typedef struct 
    {
    	int			number;
    	char*	 		question;
    	int 			type;
    	ListNode*			answers;
    } Question;
    
    typedef ListNode* ListNodePtr;
    typedef 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;
    }
    It first happens at the line in InsertAnswer

    Code:
    while(HasNext(newNode) == 1)
    which I believe corresponds to
    Code:
    if(node->next != NULL)
    As far as I can tell, it doesn't like me trying to point to a member of the pointer I have to a ListNodePtr. I'm not exactly sure how else to do it, however. Any insight into the problem would be great, I have the feeling it is something simple....

  2. #2
    *
    Guest
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Testing some code, lots of errors...
    By Sparrowhawk in forum C Programming
    Replies: 48
    Last Post: 12-15-2008, 04:09 AM
  2. Avoiding Global variables
    By csonx_p in forum Windows Programming
    Replies: 32
    Last Post: 05-19-2008, 12:17 AM
  3. file reading
    By gunghomiller in forum C++ Programming
    Replies: 9
    Last Post: 08-07-2007, 10:55 PM
  4. Game Pointer Trouble?
    By Drahcir in forum C Programming
    Replies: 8
    Last Post: 02-04-2006, 02:53 AM
  5. Stupid compiler errors
    By ChrisEacrett in forum C++ Programming
    Replies: 9
    Last Post: 11-30-2003, 05:44 PM