Menu

really hard to find bug in my proggy

K.Z.
2008-06-14
2012-09-26
  • K.Z.

    K.Z. - 2008-06-14

    Hello,

    I really need help, I can't find anything that is responsible for
    the exception my program generates,after four days and nights of futility.

    I have a class header file.
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    ifndef GENERALS_H

    define GENERALS_H

    include <string>

    class Generals
    {
    public:
    Generals();
    ~Generals();

    void iniGenerals (int cnt) ;
    void addGeneral (void) ;
        void delGeneral (int id) ;
    
    void cleanup (void) ;
    
    void setGeneral (int stat, int val) ;
    int getGeneral (int stat) ;
    void assignGeneral (int stat, int val) ;
    //returns false if general has no more provinces left else true
    bool size_arry (bool increment, int province) ;
    
    void giveProvince (int dest) ;
    void takeProvince (int id, int dest) ;
    static std::string getRandName (void) ;
    
        void printmsg (void) ;
    void displayGenerals (void) ;
    
    std::string name ;
    std::string msg ;
    
    //holds the owned provinces index number(id)
    int* provinces ;
    

    private:
    int age ;
    //generals id number
    int g_id ;
    int legions ;
    //count of owned provinces by this general
    int p_cnt ;
    };

    extern Generals* general ;
    extern int g_cnt ;
    

    endif /GENERALS_H_/

    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    the class has a pointer stored in the main source file

    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    Generals* general ;

    int main{
    ...
    ...
    ...
    }

    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    After the class is allocated into an arrayed instance...

    generals = new General[ n ] ;

    Whenever I either add or delete an instance the function....
    void addGeneral ( void ) or void delGeneral (int id ) ;
    runs its course successfully and on leaving the closing bracket
    the computer throws an unhandled exception,that only gives me
    an offset number and nothing more,except that it has created a file
    called appcompat.txt

    1)for testing purpose's I have made it so every time the program runs,
    addGeneral will be called at the press of a button

    2)It is only called in one place in all the code and I have flanked
    it with a debug function so I can trace the execution...
    ( I've also put debug functions after the opening bracket and before the closing bracket of addGeneral )
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    db( FILE, LINE, FUNCTION ) ;

    general[0].addGeneral() ;

    db( FILE, LINE, FUNCTION ) ;

    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    So what happens is this, the program executes the first flanking db() call ;
    enters addGeneral() ; prints all results of that funtion to file ; calls
    the exiting db() call.

    And instead of calling the second ( lower ) flanking db() as soon as
    addGeneral() successfully completes the program throws said exception.

    The obvious answer is 'addGeneral' is errored,but I am willing to put my
    head in a noose and say its robust.Its down below if you don't believe me.

    ( But probably horribly misaligned due to lack of code tags here )

    Its also got alot of debugging code in there to help me.

    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    void Generals::addGeneral()
    {

    db(__FILE__, __LINE__, __FUNCTION__);
    
    //utility data
    int new_p_id=0 ;
    int owner ;
    bool valid=false ;
    bool needInstance=false ;
    
    //dummy data for the getOwner method
    int id=0 ;
    int targetGeneral=0 ;
    bool dominant=false ;
    
    //temporary class member data holders
    int *tProvinces[g_cnt] ;
    int tAge[g_cnt] ;
    int tLegions[g_cnt] ;
    int tp_cnt[g_cnt] ;
    
    std::string tName[g_cnt] ;
    std::string tmsg[g_cnt] ;
    
    //find a free province to give the new general
    //i is the province id 'destination' in getOwner method
    
    for (int i=0; i&lt;MAXPROVINCE; i++){
        db(__FILE__, __LINE__);
        owner = phase.getOwner( i, id, targetGeneral, dominant, true ) ;
    
        if (owner == SENATORIAL || owner == BARBARIAN){
            province[i].clearProvince() ;
            valid=true ;
            new_p_id = i ;
    
            db(__FILE__, __LINE__, __FUNCTION__);
            break ;
        }
    }
    
    //do we need to allocate class Generals pointer 'general'
    
    if (g_cnt &lt; 1){
        g_cnt=1 ;
        needInstance=true ;
        db(__FILE__, __LINE__, __FUNCTION__);
    }
    
    if (valid &amp;&amp; (! (needInstance) )){
    
        db(__FILE__, __LINE__, __FUNCTION__);
    
        for (int i=0; i&lt;g_cnt; i++){
            tAge[i] = general[i].getGeneral( AGE ) ;
            tLegions[i] = general[i].getGeneral( LEGIONS ) ;
            tp_cnt[i] = general[i].getGeneral( P_CNT ) ;
            tName[i] = general[i].name ;
            tmsg[i] = general[i].msg ;
    
            tProvinces[i] = new int[ tp_cnt[i] ] ;
            for (int j=0; j&lt;tp_cnt[i]; j++){
                tProvinces[i][j] = general[i].provinces[j] ;
            }
    
            //delete class Generals allocated array '*provinces[n]'
    
            general[i].cleanup() ;
            db(__FILE__, __LINE__, __FUNCTION__);
        }
    
        db(__FILE__, __LINE__, __FUNCTION__);
    
        //delete the class array of instances
        delete [] general ;
        general=NULL;
    
        //increment the general counter
        g_cnt += 1 ;
        general = new Generals[g_cnt] ;
    
        db(__FILE__, __LINE__, __FUNCTION__);
    
        for (int i=0; i&lt;g_cnt-1; i++){
    
            general[i].setGeneral( AGE, tAge[i] ) ;
            general[i].setGeneral( G_ID, i ) ;
            general[i].setGeneral( LEGIONS, tLegions[i] ) ;
            general[i].setGeneral( P_CNT, tp_cnt[i] ) ;
            general[i].name = tName[i] ;
            general[i].msg = tmsg[i] ;
    
            general[i].provinces = new int [ tp_cnt[i] ] ;
    
            for (int j=0; j&lt;tp_cnt[i]; j++){
    
                general[i].provinces[j] = tProvinces[i][j] ;
            }
    
            //delete the temp holder as soon as we use it
            delete [] tProvinces[i] ;
        }
        db(__FILE__, __LINE__, __FUNCTION__);
    
        //now fill in the stats for the new general
        general[g_cnt-1].setGeneral( AGE, roll( 40, 19 )) ;
        general[g_cnt-1].setGeneral( G_ID, g_cnt-1 ) ;
        general[g_cnt-1].setGeneral( LEGIONS, 2 + roll( 8, 1 ) ) ;
        general[g_cnt-1].setGeneral( P_CNT, 1 ) ;
        general[g_cnt-1].name = getRandName() ;
        general[g_cnt-1].msg = &quot;\n&quot; ;
    
        general[g_cnt-1].provinces = new int [1] ;
        general[g_cnt-1].provinces[0] = new_p_id ;
    }// end if valid &amp;&amp; ! needInstance
    else if (valid &amp;&amp; needInstance){
        db(__FILE__, __LINE__, __FUNCTION__);
        general = new Generals [g_cnt] ;
    
        general[g_cnt-1].setGeneral( AGE, roll( 40, 19 )) ;
        general[g_cnt-1].setGeneral( G_ID, g_cnt-1 ) ;
        general[g_cnt-1].setGeneral( LEGIONS, 2 + roll( 8, 1 ) ) ;
        general[g_cnt-1].setGeneral( P_CNT, 1 ) ;
        general[g_cnt-1].name = getRandName() ;
        general[g_cnt-1].msg = &quot;\n&quot; ;
    
        general[g_cnt-1].provinces = new int [1] ;
        general[g_cnt-1].provinces[0] = new_p_id ;
        db(__FILE__, __LINE__, __FUNCTION__);
    }
    else {//do nothing since nothing is created/destroyed
        db(__FILE__, __LINE__, __FUNCTION__);
    
    }
    
    std::ofstream outfile ;
    outfile.open( &quot;c:\\bugHunter2.txt&quot;, std::ios::app) ;
    
    for( int i=0; i&lt;g_cnt; i++){
        outfile &lt;&lt; general[i].name &lt;&lt; &quot; &quot; &lt;&lt;  general[i].getGeneral( AGE ) &lt;&lt; &quot; &quot; &lt;&lt;
                           general[i].getGeneral( G_ID ) &lt;&lt;&quot; &quot; &lt;&lt; general[i].getGeneral( LEGIONS ) &lt;&lt;
                           &quot; &quot; &lt;&lt; general[i].getGeneral( P_CNT ) &lt;&lt; &quot; &quot; ;
    
        for (int j=0; j&lt;general[i].getGeneral( P_CNT ); j++){
            outfile &lt;&lt; general[i].provinces[j] &lt;&lt; &quot; &quot; ;
        }
    
    }
    
    outfile.close() ;
    //why does the program throw an exception straight after calling db
    db(__FILE__, __LINE__, __FUNCTION__);
    

    }

    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    One reason I think could be that pdcurses (this program uses it) is
    purely C and maybe theres an incompatability issue with my C++ code,
    its a last desperate retort I know.

    The information printed to file inside addGeneral is all correct,
    the general count is incremented ; the instances copied ; class destroyed ;
    rebuilt ; assigned ; the pointer temp holder deleted ; thus a new roman
    binary general is born and his complete stats are evidence he once lived.

    Like I said, bang, leave the closing bracket and CTD, after addGeneral and
    before db( FILE, LINE, FUNCTION ).

    Any ideas whatsoever ? Im out of ideas.

     
    • S. Thomas Bradley

      Hi KZ:

      You code is rather large, has almost not comments and would take anyone here hours or days to figure out what is going on. In cases like this you really should try to make a smaller example that does the same thing. This is probably why no one has answered yet.

      So I will admit that I have not spent a lot of my time going over your code. However, based on your comment "I can't find anything that is responsible for the exception my program generates." I'm guessing that you are using arrays incorrectly.

      I am sure that you remember that in C and C++ arrays are defined starting at 0 not at 1. That is, if you define an array like this: int MyArray[5]; it is defined from MyArray[0] throught MyArray[4] and that MyArray[5] is undefined. So check to see if something like that has happened, i.e. you are trying to use MyArray[5] in a statement. Look at loops for this kind of error.

      This is just basic debugging stuff anyone should know how to do. Try temporarily commenting out parts of your code, this is called "Removing Source Code in Place". Compile and run it to see if the error happens, if so uncomment that part and comment out another segment. You should eventually run it and the error doesn't occur, so you know the problem is somewhere in that segment. Don't be shy, comment out as big a block as you can, and then when you find about where it is then comment out smaller and smaller pieces of that code until you find the line of code that is the cause.

      To remove source code in place you can use the / and / comments, this has the problem of not working if you have added comments in between the / and the /. To get around this I like to use:

      if 0

      The code being remove is here

      endif

      Anyway, these are my suggestions. Hope they serve you well.

      See Ya
      Butch

       
    • K.Z.

      K.Z. - 2008-06-15

      Thanks Butch.

      To be honest I didn't really expect anyone to reply,its just got me stumped,
      and I was desperate.

      Array bounds are fine, everypart of that code is fine, after successfully leaving one
      of the two functions that call new and delete on the class the program exits
      without calling the next call to FILE LINE.

      I thought maybe the external declaration of the class pointer was in some way responsible but
      I did a smaller identical test on a test console app and it worked as expected.
      This is run on pdCurse's,being pure C I wonder if theres a compatability issue with my C++ code?

      Now I have rearranged the base code on a different compiler (dev-cpp the other was wascana)
      and set up the class as Generals general[ 4 ] instead of Generals* general ;

      But I do have the buggy version still on wascana for later inspection.

      I honestly believe this is a compatability issue rather than code error,but saying that Im
      probably wrong.

      peace.

       
    • cpns

      cpns - 2008-06-15

      Almost anything could be going wrong, and quite probably not in any part for the code that you posted. With a heap or stack corruption issue, the point of error, and the point the code crashes are unlikely to be the same, since it crashes when the corrupted or invalid data is used, not when it is damaged.

      You need to post something complete and compilable that reproduces the error to get more help than that.

      The best way to resolve this issue is to use the debugger. When run in the debugger, you can see exactly what it is baulking on, and then you can at least look for where it is getting corrupted. Unfortunately Dev-C++'s debugger is a pile of poo. Use the Insight debugger from www.mingw.org, or better yet, rebuild and debug the code in VC++ 2008 Express Edition. Even if you have no desire to use Microsoft's frankly excellent free tool, if it helps find your bug that's a good think. Besides it is always a good idea to build your code with more than one tool, since one will catch errors that another may not.

      Clifford

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.