LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   64 bit data alignment issue on CentOS 5.7 gcc 4.1.2 (http://www.linuxquestions.org/questions/programming-9/64-bit-data-alignment-issue-on-centos-5-7-gcc-4-1-2-a-925199/)

rajeshkdugar 01-23-2012 02:40 AM

64 bit data alignment issue on CentOS 5.7 gcc 4.1.2
 
While porting an application to 64 bit environment facing data alignment issues. While creating objects using new, less memory is allocated then expected. This is causing memory corruption. valgrind is also reporting invalid reads/writes.

Problem:
If I check the size of the object "sizeof(*this)" within the constructor then the size is showing as 244 bytes. But if I check the size of the object where it is created "sizeof(*ci)" then it is showing as 236 bytes.

Code:

Creating an object of class ConfigInfo as below:
  ConfigInfo *ci = new ConfigInfo();
  if (ci->init() != CI_SUCCESS)
  {
    cout << "Unable to initialize ConfigInfo instance." << endl;
  }

 class ConfigInfo
 {
  // variables
  LVPairList _parameterList;
  LVPairList _pdbaIpList;
 // size 56 bytes

  SQL    *_dbConnection;
  Mutex      _connMutex;
 //size (8+104) = 112 bytes

  char      *_localHostname;
  char      *_localIpAddr;
  char      *_remoteIpAddr;
  char      *_mySide;
  char      *_dbPref;
  char      *_dbUnpref;
  char      *_hostPref;
  char      *_hostUnpref;
  ConnectionType _myConnectionType;  //This is enum
 // size 68 bytes

 //Total = 56 + 112 + 68 = 236 bytes
 };

class LVPairList
 {
  public:
  ...
   
  protected:
    LVPair *_list;
    LVPair *_last;
    LVPair *_cursor;
    int    _count;
    // size = 28 bytes
 };


GCC version is:

$ g++ -v
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --disable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=x86_64-redhat-linux
Thread model: posix
gcc version 4.1.2 20080704 (Red Hat 4.1.2-51)


If I create a separate sample program then the allocated memory using new is same as expected, the padding/alignment is done automatically.

I could not figure out why there is a difference in the alignment in the application and in the separate sample program. I am using the same compiler flags and linking options in both the cases.
$ g++ -Wall -g -I. -I../../include -I/usr/include/mysql -c filename.cxx
$ g++ -Wall -L/usr/lib64/mysql -o <EXE> <OBJFILES> -dy -L../../lib -lconf -lmysqlclient_r -lz -lssl -lpthread


Any pointers will be helpful.

Thanks in advance,
-RKD

NevemTeve 01-23-2012 03:37 AM

Is LVPairList really defined after ConfigInfo?
Anyway, sizeof (LVPairList) should be 32 (alignment), which gives 244 total, with alignment 248

Or perhaps you used a '#pragma pack' or '-fpack-struct' unintentionally

rajeshkdugar 01-23-2012 03:53 AM

LVPairList is defined in another file.

Yes, the sizeof(LVPairList) should be 32 bytes. That is the problem I am facing. While allocating memory, its considering the size as given in my post(i.e., 28 bytes for LVPairList). But while initializing the variables its assuming the size to be 32 bytes, which is causing memory corruption.

NevemTeve 01-23-2012 04:17 AM

perhaps you used a '#pragma pack' or '-fpack-struct' unintentionally

rajeshkdugar 01-23-2012 04:39 AM

I am using "#pragma pack(1)" in some other module to make the structures single byte aligned and at the end changing it back to normal byte alignment.

I did not find ant instance of "-fpack-struct".

Anything else that may be causing the problem?

NevemTeve 01-23-2012 04:48 AM

> I am using "#pragma pack(1)" in some other module to make the structures single byte aligned and at the end changing it back to normal byte alignment.

How exactly do you that?

rajeshkdugar 01-23-2012 05:08 AM

Using "#pragma pack(8)" to change the alignment to 8 bytes.

dwhitney67 01-23-2012 05:19 AM

Quote:

Originally Posted by rajeshkdugar (Post 4581890)
LVPairList is defined in another file.

Yes, the sizeof(LVPairList) should be 32 bytes. That is the problem I am facing. While allocating memory, its considering the size as given in my post(i.e., 28 bytes for LVPairList). But while initializing the variables its assuming the size to be 32 bytes, which is causing memory corruption.

The funny thing about software is that it does not "assume" anything. It performs the actions that it was instructed to do by the programmer. So, depending on how you compiled the code or what is specified in the header file that defines LVPairList (see NevemTeve's previous posts), I find it highly dubious that LVPairList is 28 bytes in size in one area of the code, yet seen as 32 bytes in another, unless of course you are playing "tricks" with the compiler.

Back to your statement that the program (application) is assuming that LVPairList has a size of 32 bytes, how is it making this assumption? Did you hard-code the number 32 as the size, or did you rely on sizeof()?

Without knowing a few details of your application, I took the liberty to throw together the following app based on your comments that were posted previously in your code. ConfigInfo will have a size of 248 bytes, unless you pack LVPairList, which will then make the size 240. If you pack ConfigInfo, and not LVPairList, the size will be 244 bytes. If you pack both structures, then ConfigInfo will have a size of 236 bytes.
Code:

// typedefs used to fill in the "unknown"
//
typedef char  Mutex[104];  // based on OP's comment
typedef char  SQL;
typedef char  LVPair;
enum          ConnectionType {};

// Under 64-bit, all pointers, regardless of type, have a size of 8 bytes.


// LVPairList will have a size of 8+8+8+4 = 28 bytes, but when rounded
// to the next word boundary, it will have a size of 32 bytes.  If the
// structure is packed, the size will remain at 28 bytes.
//
//#pragma pack(1)
class LVPairList
{
private:
  LVPair *_list;
  LVPair *_last;
  LVPair *_cursor;
  int    _count;
};
//#pragma pack(0)


// ConfigInfo will have a size of 32+32+8+104+(8*8)+4 = 248 bytes, unless
// LVPairList is packed, in which case it will be 240 bytes.  If LVPairList
// is not packed, yet ConfigInfo is, then the size will be 244 bytes.  If both
// structures are packed, ConfigInfo will have a size of 236 bytes.
//
//#pragma pack(1)
class ConfigInfo
{
private:
  LVPairList _parameterList;
  LVPairList _pdbaIpList;

  SQL      *_dbConnection;
  Mutex      _connMutex;

  char      *_localHostname;
  char      *_localIpAddr;
  char      *_remoteIpAddr;
  char      *_mySide;
  char      *_dbPref;
  char      *_dbUnpref;
  char      *_hostPref;
  char      *_hostUnpref;
  ConnectionType _myConnectionType;
};
//#pragma pack(0)

#include <iostream>

int main()
{
  std::cout << "LVPairList    : " << sizeof(LVPairList)    << '\n'
            << "SQL pointer  : " << sizeof(SQL*)          << '\n'
            << "Mutex        : " << sizeof(Mutex)          << '\n'
            << "ConnectionType: " << sizeof(ConnectionType) << '\n'
            << "ConfigInfo    : " << sizeof(ConfigInfo)
            << std::endl;
}


johnsfine 01-23-2012 08:53 AM

Quote:

Originally Posted by rajeshkdugar (Post 4581915)
I am using "#pragma pack(1)" in some other module to make the structures single byte aligned and at the end changing it back to normal byte alignment.

If those are the only occurrences of #pragma pack in your project, then it is likely that those are somehow causing the problem.

Without seeing everything (code and build rules) it would be very hard to diagnose the exact sequence as understood by the compiler. But everything you have said indicates the header of the problem class (or a member of it) is read by the compiler in different parts of your project with different settings for pack

rajeshkdugar 01-24-2012 01:01 AM

Thanks Guys for your valuable response. One of the #pragma pack statement was set to "#pragma pack(4)" at the end of a structure to change the alignment back to normal. On the 32 bit environment it was working fine. but causing problem on 64 bit environment.

Changing the end pragma statement to “#pragma pack(8)” fixed the problem.


All times are GMT -5. The time now is 11:50 AM.