LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 01-23-2012, 01:40 AM   #1
rajeshkdugar
LQ Newbie
 
Registered: Apr 2010
Distribution: CentOS
Posts: 7

Rep: Reputation: 0
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
 
Old 01-23-2012, 02:37 AM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,856
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
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

Last edited by NevemTeve; 01-23-2012 at 02:49 AM.
 
Old 01-23-2012, 02:53 AM   #3
rajeshkdugar
LQ Newbie
 
Registered: Apr 2010
Distribution: CentOS
Posts: 7

Original Poster
Rep: Reputation: 0
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.
 
Old 01-23-2012, 03:17 AM   #4
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,856
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
perhaps you used a '#pragma pack' or '-fpack-struct' unintentionally
 
1 members found this post helpful.
Old 01-23-2012, 03:39 AM   #5
rajeshkdugar
LQ Newbie
 
Registered: Apr 2010
Distribution: CentOS
Posts: 7

Original Poster
Rep: Reputation: 0
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?
 
Old 01-23-2012, 03:48 AM   #6
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,856
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
> 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?
 
Old 01-23-2012, 04:08 AM   #7
rajeshkdugar
LQ Newbie
 
Registered: Apr 2010
Distribution: CentOS
Posts: 7

Original Poster
Rep: Reputation: 0
Using "#pragma pack(8)" to change the alignment to 8 bytes.
 
Old 01-23-2012, 04:19 AM   #8
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by rajeshkdugar View Post
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;
}

Last edited by dwhitney67; 01-23-2012 at 04:21 AM.
 
Old 01-23-2012, 07:53 AM   #9
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by rajeshkdugar View Post
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
 
Old 01-24-2012, 12:01 AM   #10
rajeshkdugar
LQ Newbie
 
Registered: Apr 2010
Distribution: CentOS
Posts: 7

Original Poster
Rep: Reputation: 0
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.
 
  


Reply

Tags
64bit, c++, centos5, gcc412



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
How to solve alignment problem in 64 -bit arch kumar_bst Linux - Embedded & Single-board computer 2 05-13-2010 09:28 AM
how to disable structure alignment using gcc compiler options ? aryan1 Programming 3 01-26-2010 08:21 AM
Compilation problem when downgrading from 64-bit gcc to 32-bit gcc huyhoang3673 Linux - Software 7 08-26-2009 11:31 AM
Data Alignment nesta Programming 6 05-01-2007 01:22 PM
GCC issue in 64 bit Linux arya Linux - Software 2 04-19-2007 03:20 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 06:57 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration