• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1147
  • Last Modified:

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;
0
1240
Asked:
1240
  • 7
  • 3
  • 3
  • +1
3 Solutions
 
evilrixSenior Software Engineer (Avast)Commented:
I'm not sure I even see why the cast is necessary. Have you tried just...

VECTOR(DB_FIELD *)::iterator i = m_vResult[set]->m_vField.begin();

m_vFieldis of type VECTOR(DB_FIELD *) so that should just work.
0
 
1240Author Commented:
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.
0
 
Hugh McCurdyCommented:
Perhaps we should explore the runtime error.
0
Transaction-level recovery for Oracle database

Veeam Explore for Oracle delivers low RTOs and RPOs with agentless transaction log backup and transaction-level recovery of Oracle databases. You can restore the database to a precise point in time, even to a specific transaction.

 
sarabandeCommented:
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
0
 
evilrixSenior Software Engineer (Avast)Commented:
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).
0
 
sarabandeCommented:
the correct statement to get a pointer to pointer was

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

Open in new window


however that would/could crash if either set was invalid index or m_vResult[set]->m_vField was empty.

so i would recommend to check for index and size before use like

if ((size_t)set >= m_vResult.size() || m_vResult[set]->m_vField.empty())
{
          // add some error handling

Open in new window


Sara
0
 
1240Author Commented:
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.
0
 
Hugh McCurdyCommented:
(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.
0
 
1240Author Commented:
Yes, this may work so how do I use and eliminate the iterator?
0
 
sarabandeCommented:
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
0
 
evilrixSenior Software Engineer (Avast)Commented:
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.
0
 
1240Author Commented:
Evilrix,

The original problem was a compile error of Solaris code in Linux with gcc/g++ 4.4. During the Linux upgrade process I removed the cast as previously noted and listed below. After running without the cast, core dumps occured that I traced back to this code. This is a large and complex application.I use to be pretty good with templates and related code years past but have been in different languages for a long time.

  VECTOR(DB_FIELD *)::iterator i =(DB_FIELD **)(m_vResult[set]->m_vField.begin());

The provided code from sara appears to access the iterator but cores on the string compare and I am now looking into the issue.
0
 
1240Author Commented:
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.
0
 
1240Author Commented:
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.
0
 
1240Author Commented:
Thanks to Sara and Evilrix
0

Featured Post

Get your Conversational Ransomware Defense e‑book

This e-book gives you an insight into the ransomware threat and reviews the fundamentals of top-notch ransomware preparedness and recovery. To help you protect yourself and your organization. The initial infection may be inevitable, so the best protection is to be fully prepared.

  • 7
  • 3
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now