0

In a program there is a pointer to a class object WordList *TheList;. WordList has subclasses WordDataList and WordDataDLinkList, so in a case statement we interpret which subclass to use and how to print out the information in the list. From what I understand in the specs, each case is supposed to declare TheList as a pointer of that type and use that, and then reclaim the memory at the end of the case so that it can be used in the next iteration of the loop. When I try something like:

    while (true)
{
    displayMenu();
    cin>>selection;
    switch(selection)
    {
    case '1':
        TheList = new WordDataList;
        TheList->parseIntoList(inf);
        TheList->printIteratively();
        delete TheList;
        break;
    case '2':
        TheList = new WordDataList;
        TheList->parseIntoList(inf);
        TheList->printRecursively();
        delete TheList;
        break;
    case '3':
        TheList = new WordDataList;
        TheList->parseIntoList(inf);
        TheList->printPtrRecursively();
        delete TheList;
        break;
    case '6':
        cout<<"Goodbye"<<endl;
        return 0;
    default:
        cout<<"I cannot understand "<<selection<<".  Try again."<<endl;
        break;
    } // switch
} // while

Deleting the pointer makes it so after the first run through no data appears (Menu still comes up) and option 2 ends up seg faulting. I'm modifying code my professor gave, and when he had no delete call, and new WordDataList and parseIntoList before the loop it ran fine. Any suggestions?

Added:

I'm reinitializing TheList in each case because I'll be adding 4 and 5 that will use WordDataDLinkList. If it's a pointer to WordDataList from outside the case statement, how would I change it to WordDataDLinkList inside when I need to? My professor wrote WordDataList for us:

   #include <sstream>
   #include <iostream>
   #include "WordDataList.h"

   using namespace std;

     WordDataList::WordDataList()
     { numWords=0; }

     bool WordDataList::incMatch(string temp)
     { for(int i=0; i<numWords; i++) {
         if (temp==TheWords[i].getWord()) {
           TheWords[i].incCount();
           return true;
         }
       }  
       return false;
     }

     void WordDataList::parseIntoList(ifstream &inf)
     { string temp;
       while (inf >> temp) 
         if (!incMatch(temp) && numWords < 10) {
             TheWords[numWords].setWord(temp);
             TheWords[numWords++].setCount(1);
         }
     }

     // Print the data iteratively
     void WordDataList::printIteratively()
   //  void printObjectArrayIterator(WordData TheWords[], int numWords)
   {
     cout<<"--------------------------"<<endl;
     cout<<"|Object  Array  Iterative|"<<endl;
     cout<<"|Word         Occurences |"<<endl;  
     cout<<"--------------------------"<<endl;
     for(int i=0; i<numWords; i++)
       cout<<" "<<TheWords[i]<<endl;
   }


     // Print the data recursively
     void WordDataList::printRecursivelyWorker(int numWords)
     //void printObjectArrayRecursive(WordData TheWords[], int numWords)
     {if (numWords==1) {
         cout<<"--------------------------"<<endl;
         cout<<"|Object  Array  Recursive|"<<endl;
         cout<<"|Word         Occurences |"<<endl;  
         cout<<"--------------------------"<<endl;
         cout<<" "<<TheWords[numWords-1]<<endl;
         return;
       }
       printRecursivelyWorker(numWords-1);
       cout<<" "<<TheWords[numWords-1]<<endl;
     }

     // Call worker function to print the data recursively
     void WordDataList::printRecursively()
     {  printRecursivelyWorker(numWords); }


     // Print the data recursively with a pointer
     void WordDataList::printPtrRecursivelyWorker(int numWords)
     //void printObjectArrayPointerRecursive(WordData* TheWords, int numWords)
     {if (!numWords)
       { cout<<"--------------------------"<<endl;
         cout<<"|Object  Array  Pointer  |"<<endl;
         cout<<"|Word         Occurences |"<<endl;  
         cout<<"--------------------------"<<endl;
         return;
       }
       printPtrRecursivelyWorker(numWords-1);
       cout<<" "<<*(TheWords+(numWords-1))<<endl;
     }

     // Call worker function to print the data recursively
     void WordDataList::printPtrRecursively()
     { printPtrRecursivelyWorker(numWords); }
  • what do you mean by after the first run through – UpAndAdam Apr 04 '14 at 19:14
  • Did you even look at the core dump? whats the back trace? – UpAndAdam Apr 04 '14 at 19:15
  • 1
    Does your base class have a virtual destructor? It would help if you posted WordList. – PaulMcKenzie Apr 04 '14 at 19:16
  • `TheList = new ... delete TheList;` is brain dead stupid (unless TheList is stupid itself) –  Apr 04 '14 at 19:16
  • 1
    @UpAndAdam, He/She more than likely means the first iteration of the while loop. Back at OP: is 'WordDataList' something you created? you may be running into an issue where calling functions from 'TheList' is using uninitialized data, check [This SO post](http://stackoverflow.com/questions/620137/do-the-parentheses-after-the-type-name-make-a-difference-with-new) and make sure you are properly initializing your 'new WordDataList' – Steve Sarcinella Apr 04 '14 at 19:18

2 Answers2

0

I think you are confused about something else. Why do you need to keep recreating the 'WordDataList' are the parse and print methods modifiying it?

If not, just create it once, and simply use the select to choose which print function to use if any.

I would also suggest putting each of the case execution statement sets into a closure, and adding some print outs or stepping through the debugger to see what is going on. Main guesses are that your 'new' is returning NULL such that you can't call its members properly OR destructor is bad.

UpAndAdam
  • 4,515
  • 3
  • 28
  • 46
0

Okay, so from what I can kindof tell: Options 1-3 should select a different subclass for your pointer TheList to hold. TheList is a pointer to your base class so that's good. What I think you need to do is new the appropriate subclass in each switch statement. I.E.

case '1': TheList = new WordDataDLinkList();

EDIT: if you intend to call a different version of each member function based off the classtype you are currently using, as in WordDataDLinkList::parseIntoList(inf), instead of WordDataList::parseIntoList(inf), try reading up on polymorphism

  • I added the parentheses, but I'm still having the same problem. – user2841264 Apr 04 '14 at 19:46
  • Is it just crashing with no error/warning? Otherwise post it here so we can take a look – Steve Sarcinella Apr 04 '14 at 19:47
  • 1,2, and 3 are still supposed to be WordDataList's. I'll add 3 and 4 later to be DLinkList's. – user2841264 Apr 04 '14 at 19:47
  • All it says when it crashes is "Segmentation fault (core dumped)" – user2841264 Apr 04 '14 at 19:52
  • Are you using an IDE that can step through the code, and see where the problem is occuring? – Steve Sarcinella Apr 04 '14 at 19:59
  • When I use GDB and get to the error, it says that it's occurring in printRecursivelyWorker. It says it happens at the line `if(numWords==1)` – user2841264 Apr 04 '14 at 20:04
  • If that function is called with numWords = 0, then it will recursively call itself with the value of -1, -2... because it would be lower than the sentinal value (end condition value). In the printPtr recursively function your professor did if(!numWords) which will end the print function when numWords == 0. Can you check if your ifstream is reading from the file correctly? Because if it has no words in the file, or can't open the filem Then you would go into this problem of not having words in your array, therefore TheWords[i-1] would segfault(access memory that is not valid). – Steve Sarcinella Apr 04 '14 at 20:18
  • I apolgize as well, because I'm sure it feels like I'm sending you all over the code. It's worth reading your code line by line in debug mode and making sure the variables you use are properly set/set to what you expect. – Steve Sarcinella Apr 04 '14 at 20:21
  • Would this problem come from not reclaiming the pointer correctly? I think that might be my main problem because the second time through my loop none of the cases will read data. Could this be because parsing into the list isn't starting from the beginning of the data file? If it doesn't read any words, word count would be 0. – user2841264 Apr 04 '14 at 20:29
  • So when you said it segfaults but displays the menu, how does it act: `1) Menu -> get input -> display values -> menu-> userinput -> segfault?` `2) Menu-> get input -> segfault` – Steve Sarcinella Apr 04 '14 at 20:30
  • Thanks for all of your help, but I got it. The problem was that the input file was never reset so it was trying to read from the end. That's why no info was read into TheList, and word count was 0. – user2841264 Apr 04 '14 at 20:36
  • Nice catch, have fun! – Steve Sarcinella Apr 04 '14 at 20:38