#38491 - cesium - Mon Mar 28, 2005 4:27 pm
I really need to squish this bug, and I've got a DS that I rarely use so... if you are the first person to find the root cause of the problem described below, I'll send you a Dual Screen. See the comments for details. Yell if you need the makefile.
cesium
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]; } |