Game Development Community

Linked List causing Crash on Start

by Robert Fritzen · in Technical Issues · 07/17/2011 (11:30 am) · 3 replies

Hello, I'm having a problem with a linked list definition.

It's crashing as soon as I try to add an item to the list.

class ItemDefinitions {

private:
.
.
   typedef struct itemNode {
      String item;
	  itemNode *next;
   };
   itemNode *head;
.
public:
.
.
};

ItemDefinitions::ItemDefinitions() {
   head = NULL;

   declareItems();
}

void ItemDefinitions::declareItems() {
   //call exec on the store
   Con::evaluatef("AssignDefinitions();"); //adds the items to the list.
   //validate and activate
   itemList->validateItems();
   itemList->activate();
}

void ItemDefinitions::addItem(const char * itemDetails) {
   itemNode * newNode;
   itemNode * nodePtr;
	   
   newNode = new itemNode;
   newNode->item = itemDetails;
   newNode->next = NULL;

   if(head == NULL) {
      head = newNode;
   }
   else {
      nodePtr = head;
	  while(nodePtr->next != NULL) {
		 nodePtr = nodePtr->next;
	  }
	  nodePtr->next = newNode;
   }
}

No idea why it's crashing. This same code was working 2 days ago, and I haven't made any changes here.

I'm getting an Access Violation Reading Location crash.

#1
07/17/2011 (1:08 pm)
void ItemDefinitions::addItem(const char * itemDetails) {  
   itemNode * newNode;  
   itemNode * nodePtr;  
         
   newNode = new itemNode;  
   newNode->item = itemDetails;  
   newNode->next = NULL;  
  
   if(head == NULL) {  
      head = newNode;  
   }  
   else {  
      nodePtr = head;  
      while(nodePtr->next != NULL) {  
         nodePtr = nodePtr->next;  
      }  
      nodePtr->next = newNode;  
   }  
}

I believe your code there is causing the issue, I'm using linked lists in my own software (not related to Torque) and it's working fine. However it is using a different method of adding elements to your linked list (works under GCC, I'm not sure about MSVC):

#include <string>

struct LinkedListNode
{
   public:
   LinkedListNode(void) : itemData(NULL),
   Next(NULL)
   {
   }

   ~LinkedListNode(void)
   {
      if (Next != NULL)
         delete Next;
   }

   //! Data
   std::string itemData;
   LinkedListNode *Next;
};

LinkedListNode *linkedListHead = NULL;

void addElement(std::string element)
{
   LinkedListNode *NewNode;
   NewNode = (LinkedListNode*)malloc(sizeof(LinkedListNode)); //allocate space for node
   NewNode->itemData = element;
   NewNode->Next = linkedListHead;
   linkedListHead = NewNode;
}
#2
07/17/2011 (1:41 pm)
This still does not work (even with provided fixes). Here is the entire code, since it seems that it could potentially be linked to some other issue?

//HEADER
#ifndef _ITEMDEFS_H_
#define _ITEMDEFS_H_

#include "console/console.h"
#include "console/consoleInternal.h"

#include "platform/platform.h"
#include "console/simBase.h"
#include "console/consoleTypes.h"
#include "console/scriptObjects.h"
#include "console/simBase.h"

#include "core/strings/stringUnit.h"

#include "console/PGDCrypto/cryptoPackage.h"

#define _DEBUG 1

class ItemDefinitions {

private:
   int itemCount;
   bool active;

   //linked list
   struct itemNode {  
      public:  
		 itemNode(void) : item(NULL), next(NULL) {}   
         ~itemNode(void) { if (next != NULL) delete next; }
		 String item;  
         itemNode *next;
   };
   //end
   itemNode *head;

   InvertibleRSAFunction keys;

   static const int costVar[];

public:
   ItemDefinitions();
   ~ItemDefinitions();

   static void create();
   static void destroy();

   void validateItems();
   void activate();
   void addItem(const char * itemDetails);

   void declareItems();

};

extern ItemDefinitions* itemList;

#endif

//CODE
#include "console/PGDCrypto/itemStore.h"

ItemDefinitions* itemList = NULL;

const int ItemDefinitions::costVar[] = {100, 1000, 2500, 5000, 10000, 50000, 250000, 500000, 1000000};

void ItemDefinitions::create() {
   if(itemList == NULL) { 
      itemList = new ItemDefinitions();
   }
}

void ItemDefinitions::destroy() {
   delete itemList;
   itemList = NULL;
}

ItemDefinitions::ItemDefinitions() {
   itemCount = 0;
   active = false;
   keys = cryptoPackage->rsaGenerate(512);

   declareItems();
}

ItemDefinitions::~ItemDefinitions() {

}

void ItemDefinitions::validateItems() {
   std::string sign, toSign;
   //for(int i = 0; i < itemCount; i++) {
   itemNode *nodePtr = head;
   while(nodePtr->next) {
      sign = "", toSign = "";
      toSign = string(nodePtr->item.c_str());
      //do signing here...
	  cryptoPackage->rsaSign(keys, toSign, sign);
	  //append it to the string
	  //item[i].AppendString("t");
	  nodePtr->item += 't';
	  nodePtr->item += sign.c_str();

	  nodePtr = nodePtr->next;
   }
}

void ItemDefinitions::activate() {
   active = true;
   std::string test, signature;
   itemNode *nodePtr = head;
   while(nodePtr->next) {
      //strip the fields
	  test = Con::getReturnBuffer( StringUnit::getUnits(nodePtr->item.c_str(), 0, 5, "tn") );
      //strip the signature	  
	  signature = Con::getReturnBuffer( StringUnit::getUnit(nodePtr->item.c_str(), 6, "tn") );
	  //verify the signature
	  if(cryptoPackage->rsaVerify(keys, test, signature) == false) {
	     active = false;
		 break; //signature invalidation detected, the activation will now halt.
	  }

	  nodePtr = nodePtr->next;
   }
}

void ItemDefinitions::addItem(const char * itemDetails) {
   itemNode *NewNode;  
   NewNode = (itemNode*)malloc(sizeof(itemNode)); //allocate space for node  
   NewNode->item = itemDetails;  
   NewNode->next = head;  
   head = NewNode;  
}

void ItemDefinitions::declareItems() {
   //call exec on the store
   Con::evaluatef("AssignDefinitions();");
   //validate and activate
   itemList->validateItems();
   itemList->activate();
}

ConsoleFunction(addItem, void, 2, 2, "adds an item to the list.. not validated until ValidateItems()") {
   itemList->addItem(argv[1]);
}

Output:
'BattlelordAD.exe': Loaded 
.
.
.
'BattlelordAD.exe': Loaded 'C:WindowsSysWOW64msimg32.dll'
'BattlelordAD.exe': Loaded 'C:WindowsSysWOW64msvcr71.dll'
'BattlelordAD.exe': Loaded 'C:WindowsSysWOW64XAudio2_7.dll'
'BattlelordAD.exe': Loaded 'C:WindowsSysWOW64rsaenh.dll'
First-chance exception at 0x0066fdef in BattlelordAD.exe: 0xC0000005: Access violation reading location 0x00000008.
Unhandled exception at 0x0066fdef in BattlelordAD.exe: 0xC0000005: Access violation reading location 0x00000008.
#3
07/20/2011 (6:30 am)
After chatting with Robert MacGregor (one of my fellow dev team members), we sorted this issue out. I was incorrectly initializing my linked list (IE: trying to validate items in it before the list was even filled).