gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Help Wanted > Seeking programmer to find bug.

#38443 - cesium - Sun Mar 27, 2005 9:41 pm

I have developed an example program that illustrates some problems I am having with devkitarm-r11. If you are interested in solving this problem, I'd gladly pay you to do so. Let me know your price and payment terms. The makefile is available if needed.
cesium
Code:

//main.cpp
/*
   This code illustrates a problem I'm having with devkitarm-r11.
   I don't know if it is a bug in the compiler, or a bug in my code.
   I have distilled my code into the following templated class: DataSet,
   and a templated function: genDataSet.
   I think these are the bare minimum structures that produce the problems.
   I have observed this problem on actual hardware and in VisualBoyAdvance-SDL-1.7.2.

   The problem seemed to morph as I was chopping down the code. Here is a
   description of the current form as I have seen it using the Insight debugger
   connecting to VisualBoyAdvance-SDL-1.7.2.

   First off, a few definitions:
      I'll use the term "Step into" to refer to Insight's Step(S) function.
      I'll use the term "Step over" to refer to Insight's Next(N) function.
      I'll use the term "Step out of" to refer to Insight's Finish(F) function.
      
   -Compile and load up the code in VisualBoyAdvance and Insight.
   -Have Insight connect to VBA and run up until the line commented as: POINT A.
   -This is an assignment statement that calls the genDataSet function.
      The strange stuff happens during this assignment. The way I watch this
      assignment happen is to step into the function and then "step into the
      return process." That sounds odd, but I'll describe it.
   -Step into the function genDataSet. Run up until the line: POINT B.
   -Step into this return.
      You'll end up in a DataSet destructor. Step out of this destructor.
   -You're back at POINT B. Step into it again.
      You'll be in some odd looking code that says Unwind. Step out.
   -You're back at POINT B. Step in again.
      Now we're someplace interesting, the assignment function DataSet<T>::operator=()
   -Step over twice so that you get to POINT C, where the new operator is called.
   -Step into the new operator.
      Something odd happens, we end up at the bottom of main(). Is this bad? A debugger flaw?
      Step out of this point at the end of main.
   -We're back at POINT C. Step into the new operator again.
   -Now we get to the good part. Here we are at POINT D in the DataSet constructor.
      Step over the assignment: m_allocUnit=10
      I find that m_allocUnit now contains 0, not 10.
   -Step into POINT E, the call to NEW.
   -I get a SIGTRAP message from the debugger. I have no idea what's going on.
   -Step into the NEW function. n is not 0, it is not 10, it is 2560!! huh?

  If you can help me determine if this is a compiler or a programmer problem,
  I'd be very grateful.

  I'm interested in solutions like:
   "Hey, you dummy, you can't to that in C++, it's not allowed, here's why..."
   or
   "Yea, this is a known bug in gcc ver x.y.z, here's a workaround.

  I'm not interested in solutions like:
   "Why don't you just write your code like this, <snip> and then the
   problem goes away!"

  I'd like to know the root cause of this problem, since I have a few
  thousand lines of code that "boil down" to this example.

  Thanks,
  cesium

*/

//templated NEW function to help debug strange values passed to new.
template<class T> T* NEW(unsigned int n);
//templated container class.
template <class T> class DataSet  {
public:
   DataSet();
   DataSet(const DataSet& x);
   DataSet<T>& operator=(const DataSet<T>& x);
   ~DataSet();
private:
   unsigned int m_allocUnit;
   T* mp_data;
};
template <class T> DataSet<T>::DataSet() {
   m_allocUnit=10;//POINT D
               //1 to 9 seem to work, but 10 and above do not.
               //If this value is 10, the debugger shows it getting a
               //value of 0, but the call to NEW below gets 2560. doh!

   //mp_data=new T[m_allocUnit];//Usual way of allocating RAM,
                        
   mp_data=NEW<T>(m_allocUnit);//I used my NEW function to see what's happening.
}
template <class T> DataSet<T>::DataSet(const DataSet<T>& x) {
   m_allocUnit=x.m_allocUnit;
   mp_data=new T[m_allocUnit];
}
template<class T> DataSet<T>& DataSet<T>::operator=(const DataSet<T>& x) {
    if (&x != this) {
      m_allocUnit=x.m_allocUnit;
      T* p_t=new T[m_allocUnit];//POINT C
      delete mp_data;
      mp_data=p_t;
   }
   return *this;
}
template <class T> DataSet<T>::~DataSet() {
   delete mp_data;
}

//A templated function that returns a DataSet.
template<class T> DataSet<T> genDataSet(void);

int main(void) {
   //set is a DataSet of DataSets. You might do this to create a 2 dimensional vector.
   DataSet<DataSet<unsigned int> > set;
   set=genDataSet<DataSet<unsigned int> >();//POINT A
   return 0;
}
template<class T> DataSet<T> genDataSet(void) {
   DataSet<T> ret;
   DataSet<T> tSet;
   ret=tSet;
   return ret;   //POINT B
}
//Diagnostic routine to look at value passed to new.
template<class T> T* NEW(unsigned int n) {
   if (n==2560) {   //sometimes wierd values get passed to NEW.
      unsigned int dummy=0;
      while (1) {
         dummy++;   //trap for goofy value, when m_allocUnit was supposed to be 10.
      }
   }
   return new T[n];
}


#44108 - fstark - Mon May 30, 2005 12:18 pm

(Okay, this looks like an old post, so it is probably already fixed, but as I was reading this post and it compelled me into registering, I may as welll answer it...)

No need to pay, dude. Just use delete[] instead of delete and you problem will go away...

Allocated by new[] => free'd by delete[].

(Btw, that's IMHO some seriously ugly code, but hey, you didn't ask for that kind of info :-) )

Cheers,

--fred

#44155 - sajiimori - Mon May 30, 2005 6:45 pm

Yes, it was solved shortly after being posted in another section. :)