1240
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: 8c4401476b260ed4dfa10868f7 ed486b
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_itera tor<DB_FIE LD**, 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_NbrRo ws)
return NULL;
// @@ Problem with below line @@
VECTOR(DB_FIELD *)::iterator i = (DB_FIELD **)(m_vResult[set]->m_vFie ld.begin() );
for(; i != m_vResult[set]->m_vField.e nd(); 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;
--------------------------
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: 8c4401476b260ed4dfa10868f7
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_itera
--------------------------
// Method containing bad Linux cast
const DataItem *DBAccess::Item(int set, int row, const char *pName) const
{
if(row >= m_vResult.at(set)->m_NbrRo
return NULL;
// @@ Problem with below line @@
VECTOR(DB_FIELD *)::iterator i = (DB_FIELD **)(m_vResult[set]->m_vFie
for(; i != m_vResult[set]->m_vField.e
{
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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
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
you could get a pointer to pointer without cast by
DB_FIELD ** p = &m_vResult[set]->m_vField.begin();
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).
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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.
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.
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:
Sara
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];
}
}
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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.
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.
ASKER
Thanks to Sara and Evilrix
ASKER