LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   32-bit to 64-bit migration for c++ program (https://www.linuxquestions.org/questions/programming-9/32-bit-to-64-bit-migration-for-c-program-613579/)

newbix 01-14-2008 07:47 PM

32-bit to 64-bit migration for c++ program
 
Hi,

I am trying to port a large c++ program I wrote on a 32-bit machine to a 64-bit opteron system and, not surprisingly, I am having problems. The program doesn't crash or anything, it just spits out results that are completely wrong at the end. I do not have the option of using the "-m32" switch with the "g++" compiler I am using, although this would work, because that option has been disabled and is not supported on the machine I am migrating to. So the only option I can see is to sift through the code and fix all the migration issues (groan).

My question is this: does anyone know of g++ compiler switches, or some linux program that can flag potential 32-to-64-bit migration issues in a c++ code? This would make my job incredibly easier.

Many thanks in advance!

rmallins 01-15-2008 04:33 AM

The closest thing to the tool you're after would be a static analysis tool (lint is the usual example for C, but doesn't do C++)
http://en.wikipedia.org/wiki/List_of..._code_analysis
however you may not like the results as they flag up anything they find less than ideal about your code. They can often flag portability issues, but they will also find a lot more besides - not necessarily what you're after.

I'm afraid I don't know of a tool that does exactly what you want, but perhaps in future you may want to use the C99 fixed size types (uint8_t, int8_t, uint16_t, int16_t, etc...) to be sure of the size of data you're using (I work in embedded software where we often have this issue). The porting issues you're seeing are usually caused by programmer assumption about the size of a give type; for example the coder may assume that a pointer is the same size as an int, and cast between them, only to find on a new architecture that the cast becomes a truncation and loses information. (Neither C nor C++ guarantees the size of any traditional type, though int is *usually the native bus width of the system and char is usually a byte).

*when using gcc with the -m64 option an int is defined as 32bits on a 64 bit system - so breaks this rule.

Such programmer assumptions would be very difficult for a compiler to spot as the compiler cannot understand what assumptions you're making when writing the code. I think this is why the feature doesn't exist yet (AFAIK).
As regards finding the bugs, cast operations are often a prime suspect. If you've used the c++ style of casting - "xxxxx_cast<>()" then it will be fairly easy to grep for them and hopefully flush out some suspicious code. Other things to watch for, are if you're initialising variables which you use to mask others. For example if you tried to set a variable to all "1s", e.g

unsigned int bitmask = 0xFFFFFFFF;

This would work well for a 32bit int but only set half of a 64bit int. Two ways to do this sort of thing flexibly are:

unsigned int bitmask = static_cast<unsigned int>(-1);
unsigned int bitmask2 = ~0;

which will both set an unsigned var to all "1"s however big or small its type is. To make your mask you can then clear bits individually as required.

Apologies if you know this already - hopefully it will be of some help in future.

Good luck!

greeneagle 01-15-2008 04:50 AM

I haven't found a method to do this neatly I'm afraid.
Ported some things from 32bit to 64 over last while and it boiled down to a couple of common things. It was not quite as bad as I expected so just go for it! :)

Pay attention to warnings, sometimes they point to problems (but sometimes not really).
-Wall -Wcast-align

And if you want to quickly fix a good few problems turn off optimisation!
You might try a build without optimisation and see does it get further.
-O1 instead of -O2 or -O3 or whatever.

Did I keep a list? *rummage* Oh. Found some notes on the matter.
But they're rather specific to what I was doing.

dereferencing type-punned pointer will break strict-aliasing rules
cast from '<sometype>' to '<something else>' increases required alignment of target type

http://en.wikipedia.org/wiki/Type_punning
wikipedia/Type_punning wikipedia/Type_punning
http://www.opensolaris.org/jive/thre...=1923&tstart=0
So by removing these warnings we allow the compiler to better optimise.
http://msdn2.microsoft.com/en-us/library/ms861546.aspx
reinterpret_cast
http://www.codeproject.com/cpp/static_cast.asp
codeproject/static_cast
http://publib.boulder.ibm.com/infoce...tatic_cast.htm
static_cast to subclass

newbix 01-15-2008 07:27 PM

Problem solved (I hope)!
 
Thank you rmallins and greeneagle. I took your suggestions to heart and went through the code looking for suspicious statements, and I found the culprit! It was all due to a single line where I was calling the "pow" function with "long double" arguments. I changed the "pow" to "powl" and now the code works under both 32-bit and 64-bit architectures.

Still, I consider myself very lucky to have found the problem this quickly. If you or anyone else finds a more systematic and automated way of flagging these potential migration problems at some point in the future, I would love to hear it. I'm never this lucky twice in a row...

Many thanks again!


All times are GMT -5. The time now is 07:11 PM.