0

I'm making a program utilizing classes and am getting a strange error but only on occasion. I believe that the error is caused by either a stack overflow or one of my pointers in messed up. When I run my program it will loop through a few times and add my record class to the list, but once it gets to the 3rd item I get a SIGSEGV Segmentation Fault error. When I use GDB and step through my program and try to print the value of 'current -> id' it says "Cannot access memory at address 0xe0". Here is the part of my code I'm having trouble with, which is supposed to perform a deep copy into another list.

list&list :: operator=( const list& list1 )
{
    rec * current = NULL;
    current = list1.first;

    rec temprec;
    char tempid[15];
    char tempfirst[15];
    char templast[15];
    int answersin[10];

    while( current -> id != NULL)
    {
        //Printing Data to follow program easier
        cout << endl;
        cout << tempid;
        cout << endl;
        cout << current -> id;  //Receive error on this line
        cout << endl;

        strcpy(tempid, current -> id);
        strcpy(tempfirst, current -> firstname);
        strcpy(templast, current -> lastname);
        for(int i=0; i<10; i++)
        {
            answersin[i]=current -> a[i];
        }
        temprec.SetData( tempid, tempfirst, templast, answersin );
        if ( AddItem( temprec ) )
        {
            cout << "Success.";
        }
        else
        {
            cout << "Failed.";
        }
        current = current -> next;          
    }

} // End Operator =

If it is a stack overflow what is the best way to go about fixing it? I'm not exactly sure what should get stored in the Heap vs the Stack. I have checked my pointers and they seem okay to me, but I could be wrong. Any help is greatly appreciated!

Edit 1: I discovered that my problem is that the list I was passing in was not null terminated. If I make a list in my main program I have no problem, but when I make my list within this function it messes up (still only sometimes, I believe only on larger lists). This function is supposed to compare a selected person's answers with another and make a list containing the records with the most matches.

    list list :: BestMatch ( char *IDinput )
{
    rec * ptr;        // pointer for traversing
    ptr = first;      // set pointer to the beginning of the list
    rec * CompPtr;    // pointer for traversing to compare answers
    CompPtr = first;  // set compare pointer to the beginning of the list
    int compare = 0;  // variable to compare strings
    int score = 0;
    int currentMax = 0;
    list returnList;

    while (ptr)  // loops through until the end of the list
    {
        compare = strcmp( IDinput, ptr -> id );  // compare id to be Matched to the id that ptr points to
        if ( compare == 0 )  // "if id to be Matched matches an id in the list"
        {
            break;  // break from loop
        }
        ptr = ptr -> next;  // go to the next node in the list to be checked
    }
    if (!ptr) // If ptr = NULL, meaning the end of the list was reached
    {
        cout << "ID for Match Not found." << endl;
        return returnList;
    }
    while (CompPtr) // loops through until all the answers are compared
    {
        score = ComputeScore ( ptr, CompPtr ); // Compares answers from id to be Matched to current node in the list
        if ( score == 0)
        {
            ; // Do nothing
        }
        else if ( score > currentMax )
        {
            returnList.DeleteList();          // Delete all other items in list because new score is greater than all of them
            if ( returnList.AddItem( *CompPtr ) )  // Add new item with highest score to the list
            {
                cout << "\nSuccess!\n";
            }
            else
            {
                cout << "\nMatch.\n";
            }
            currentMax = score;             // Make the new current max be equal to the score of the new greatest match
        }
        else if ( score == currentMax )
        {
            returnList.AddItem( *CompPtr );  // Simply add to list due to same score
        }
        else //(score < currentMax)
        {
            ; //Do nothing.
        }
        CompPtr = CompPtr -> next; // advance to the next node to be compared
    }
    ptr = NULL;
    CompPtr = NULL;
    returnList.PrintList( 0 );
    return returnList;
} // End BestMatch

The ComputeScore function that is used:

    int list :: ComputeScore ( rec* Input, rec* Compare)
{
    int ReturnScore =0;
    int compare =0;

    // Prevents comparing to self
    compare = strcmp(Input -> id, Compare -> id);
    if (compare == 0)  // id match found
    {
        return 0; // cannot match with self
    }

    // Check to see if gender is appropriate for match
    if ( Input -> a[9] != Compare -> a[0] )
    {
        return 0;
    }
    else
    {
        ;
    }

    // Check to see if school year is appropriate for class
    if ( Input -> a[7] == 1 && Compare -> a[1] != 1 )
    {
        return 0;
    }
    else if ( Input -> a[7] == 2 && Compare -> a[1] != 2 )
    {
        return 0;
    }
    else if ( Input -> a[7] == 3 && Compare -> a[1] != 3 )
    {
        return 0;
    }
    else if ( Input -> a[8] == 4 && Compare -> a[2] != 4 )
    {
        return 0;
    }
    else
    {
        ; // Do nothing & Continue
    }

    // Compare other answers
    if ( Input -> a[2] == Compare -> a[2] )
    {
        ReturnScore = ReturnScore + 1;
    }

    if ( Input -> a[3] == Compare -> a[3] )
    {
        ReturnScore = ReturnScore + 1;
    }

    if ( Input -> a[4] == Compare -> a[4] )
    {
        ReturnScore = ReturnScore + 1;
    }

    if ( Input -> a[5] == Compare -> a[5] )
    {
        ReturnScore = ReturnScore + 1;
    }

    if ( Input -> a[6] == Compare -> a[6] )
    {
        ReturnScore = ReturnScore + 1;
    }

    if ( Input -> a[8] == Compare -> a[8] )
    {
        ReturnScore = ReturnScore + 1;
    }

    return ReturnScore;

} // End ComputeScore

and some addition information that may be helpful from my header file:

class rec
{
public:
    rec ( char * i, char * fn, char * ln, int * ans );  //constructor
    rec ( void );                                       //default constructor
    rec& operator=( const rec& r );                     
    rec ( const rec& r );                               //copy constructor
    ~rec( );
    void SetData( char * id_in, char * fn, char * ln, int * ans_in );       
    char ReturnID ( const rec& r );
    void Print( );      
    friend class list;
private:
    char id[15];
    char firstname[15];
    char lastname[15];
    int a[10];
    rec* prev;
    rec* next;
};

class list
{
public:
    list ( void );                          //default constructor
    list& operator=( const list& list1 );   //deep copy one list to another
    int AddItem ( const rec& r );
    int DeleteItem ( char* delid );
    void PrintList ( int order );
    int Count(char *FileName);
    void DeleteList ( );
    int ReadData ( char* file1, char* file2 );
    int WriteData ( char* wfile1, char* wfile2);
    int ComputeScore ( rec* Input, rec* Compare);
    list BestMatch ( char* IDinput );
    list TopTen ( char* IDinput );
private:
    rec * first;
    rec * last;
};
Lareaper
  • 31
  • 1
  • 6
  • "Cannot access memory at address 0xe0" sure sounds like you are trying to dereference a member variable through a NULL pointer (e.g. struct * something = NULL; something->foo = 123, where foo is at offset 0x0e from the top of the struct's memory area) – Jeremy Friesner Apr 24 '16 at 03:35
  • I thought the same but just found out that for some reason my list ins't null terminated. The next field of the last item contains the address 0xe0 instead, which is giving me my problem. – Lareaper Apr 24 '16 at 04:21
  • You can catch `SIGSEGV` with a signal handler in your code and trace the source of your problem. http://stackoverflow.com/questions/2663456/how-to-write-a-signal-handler-to-catch-sigsegv – Niklas Rosencrantz Apr 24 '16 at 03:27

1 Answers1

2

For the last element in the list, its next will be NULL, so after current = current -> next;, current will be NULL, and you are yet dereferencing it via current->id. So I suggest adding this check in the while loop:

while(current && (current -> id != NULL)) {
    ...
}
fluter
  • 13,238
  • 8
  • 62
  • 100
  • I tried this and was still getting the error. I added an extra print function for the list I'm passing in (which I also have print the memory address of previous and next for each item in the list) and I realized that my list isn't null terminated for some reason, and instead the next field of the last item has the address 0xe0. I never had this problem before with my program which I've been modifying and adding to for a while, so I'm not sure what is going on. – Lareaper Apr 24 '16 at 04:19
  • @Lareaper So you found there is an invalid address 0xe0, ok, please post the code that constructs the list. – fluter Apr 24 '16 at 04:33
  • I am not sure if that is where the problem is or if it's in one of my other class functions I'm using, but I'll post up some more code! – Lareaper Apr 24 '16 at 04:36
  • There certainly some code that touched the list, I'm not sure about your program so I'm just guessing. – fluter Apr 24 '16 at 04:39
  • You are correct the code did, sorry I hadn't posted enough code. I added more now. – Lareaper Apr 24 '16 at 18:32