Link to home
Start Free TrialLog in
Avatar of 1240
1240Flag for United States of America

asked on

C++ Casting error in Linux Centos 6.3 - Works in Solaris

I have a casting error that was introduced in a compiler upgrade from Solaris to Linux CentOS 6.2. Can anyone help resolve?
-----------------------------------------------------------
Compile Error:
GNU C++ (GCC) version 4.4.6 20120305 (Red Hat 4.4.6-4) (x86_64-redhat-linux)
      compiled by GNU C version 4.4.6 20120305 (Red Hat 4.4.6-4), GMP version 4.3.1, MPFR version 2.4.1.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 8c4401476b260ed4dfa10868f7ed486b
source/dbaccess.cpp: In member function ‘virtual const DataItem* DBAccess::Item(int, int, const char*) const’:
source/dbaccess.cpp:184: error: invalid cast from type ‘__gnu_cxx::__normal_iterator<DB_FIELD**, std::vector<DB_FIELD*, std::allocator<DB_FIELD*> > >’ to type ‘DB_FIELD**’
-------------------------------------------------------------------------



// Method containing bad Linux cast
const DataItem *DBAccess::Item(int set, int row, const char *pName) const
{
   if(row >= m_vResult.at(set)->m_NbrRows)
      return NULL;

  // @@ Problem with below line @@
   VECTOR(DB_FIELD *)::iterator i = (DB_FIELD **)(m_vResult[set]->m_vField.begin());
   for(; i != m_vResult[set]->m_vField.end(); i++)
   {
      if(stricmp((char *)((*i)->Name.c_str()), pName) == 0)
         return (*i)->Item[row];
   }
   return NULL;
}

------------------------------------------------------------------------
 typedef struct _DATABASE_RESULT_SET_
   {
      int                           m_RowsAffected;
      int                           m_NbrCols;
      int                           m_NbrRows;
      VECTOR(DB_FIELD *)       m_vField;
   } DB_RESULT;
SOLUTION
Avatar of evilrix
evilrix
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of 1240

ASKER

Yes, I have removed the cast and compiles with no issue but have a runtime error on this code. Was exploring options and since runs on Solaris but not Linux, the cast is my concern before moving on.
Perhaps we should explore the runtime error.
with older compilers, the iterator of standard template containers were typedef'd as pointer to array element, what is in your case DB_FIELD**. in nowadays c++, iterators of template containers were class type and the begin member functions returns a reference to a class object. if they don't provide a cast operator in the iterator class to turn an iterator to a pointer the C cast you used necessarily will fail.

you could get a pointer to pointer without cast by


DB_FIELD ** p = &m_vResult[set]->m_vField.begin();

Open in new window


but that will not help you further if the runtime error occurs because m_vResult[set] is invalid what easily could be if 'set' is an invalid index.

Sara
The fact this worked on Solaris is no indication the code was error free. Often, errors result in undefined behaviour and that means exactly what it says on the tin. The result is that code could actually work but if it does it isn't by design. The fact that this code fails when compiled on Linux using gcc leaves me to conclude that there are other problems in the code.

What is the error you are getting on gcc? Have you tried building the code with the -g flag and optimizationn turned off and then running it in the gdb debugger?

>> the cast is my concern before moving on.
As Sara has pointed out, the implementation details of an iterator are opaque. The standards documentation defines what an interator must do but how the iterator is implemented is left up to the vendor. It is best to not assume anything about an iterator other than it is of type container<T>::iterator (where container is one of the STL containers). Any other assumptions you make about the type will be non-portable (as you've discovered).
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of 1240

ASKER

Ok, let me smoke over the iterator discussion and try some options. I have debugged with gdb which is how I got to this point.
(No points for this please.  I'm just being supportive.)

My guess is that Sara is right on the money.  Please follow her recommendation about index and size.

Evilrix is also right about how compilers can vary even on the same platform.  I worked on a program that worked flawlessly for thousands of users for well over a decade.  Then in one week many years ago, two different users reported the same crash.  The others still didn't.

I'm glad you are following Sara & Evilrix's advice.  I think you'll get this solved.
Avatar of 1240

ASKER

Yes, this may work so how do I use and eliminate the iterator?
you should try suggestion of evilrix and use iterator type rather than pointer to pointer. but to make it sure you should check on index and empty vector:

VECTOR(DB_FIELD*)::iterator i;
if ((size_t)set < m_vResult.size() && !m_vResult[set]->m_vField.empty())
{
        // here you can safely use the iterator i
        for(; i != m_vResult[set]->m_vField.end(); i++)
        {
             // but row als must be checked
             if(stricmp((*i)->Name.c_str()), pName) == 0 && (size_t)row < (*i)->Item.size())
                  return (*i)->Item[row];
        }
}

Open in new window


Sara
BTW: You still haven't told us what the runtime error actually was. That info is probably important if we're to help you finalise a solution.
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of 1240

ASKER

This post came across as being all over the board and I appreciate the effort by all. The problem may be more of bad data that is not being processed under a few conditions. For simplicity sake, let me close this thread and open a new on when I have more information to provide in a logical order. Thanks to Sara and Evilrix for the valuable information.
Avatar of 1240

ASKER

I came across as being all over the board in this post and I appreciate the effort by all. For simplicity sake, let me close this thread and open a new on when I have more information to provide in a logical order. Thanks to Sara and Evilrix for the valuable information.
Avatar of 1240

ASKER

Thanks to Sara and Evilrix