64位移植 [英] 64 bit porting

查看:71
本文介绍了64位移植的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,


我们正在努力将用C和C ++编写的产品从32位

移植到64位。我们需要在

未来维护32位和64位版本。我们使用32位源代码并使用64位
编译器进行复制并修复了所有编译警告。通过罚款编制了

,但产品在很多地方都破了。我们理解

将32位代码移植到64位平台不仅仅是b
编译的问题。由于从ILP32到LP64的更改,我们必须处理编译器无法捕获的问题

。因此,我们正在尝试

列出可能因为长度和指针从4字节到8字节的变化而导致的所有可能出现的问题。 />
仍然是4个字节。我们已经列出了几个地方的可能性

,其中错误可能会蔓延。我们想要验证

点的正确性,并希望在此列表中添加更多内容。请帮助我们。


1.盲目地将所有长整数改为整数。但不是长整数。

我们认为这可能会解决以下问题

(a)使用按位运算符编写的代码,假设大小为

long是4将产生问题

(b)通过不使用

OFFSET宏获取结构中字段的偏移量会在结构长度

(c)通过使用

指针(如long i = 1)来逐字节操作长数据; char a =((char *)& i)[0];

等.....


2.检查所有库函数返回long,就像atol

并确保没有代码写入,假设reaturn值

是4个字节。或者考虑将atol更改为atoi或simlar函数。


3.如果使用C风格的内存分配,则使用new命令。然后有错误的可能性。

long * ptr = malloc(4 * 2);
32位编译中的
上述声明将分配8个字节的

内存和ptr可以用作两个元素的数组。

但是在64位编译中它将分配8个字节和

数组中的元素是一个。因此,如果编写代码

,假设元素的数量是2,那么它将会中断。所以

所有mallocs" calloc" s和realloc应该被检查。


4.如果指针被转换为必须在任何地方整数

检查。

例如

int a = 10;

int * ptr =& a;

int b = reinterpret_cast< int>(a);

以上代码将在64位编译中产生问题,因为

指针是8个字节,int是4个字节。所以必须将

更改为

long b = reinterpret_cast< long>(a);


5.获取通过假设字段的大小为

字段并且不使用OFFSET宏来偏移结构字段。这个东西怎么样?b $ b在工会或班级的情况下工作


6. size_t是32位编译的32位数量,其中它增长了
64位编译时
到64.


7.格式说明符应该在printfs和scanfs中检查



long i =< some expression> ;;

printf("%d",i);

就结果而言不会是个大问题收敛但是它会打印错误的值,当值为i时非常大,超过整数限制。


非常感谢你的时间。


问候,

Mohan。

解决方案

在< 9b ************************** @ posting.google.com> mo************@msn.com (Mohanasundaram)写道:

我们正在努力将用C和C ++编写的产品从32位移植到64位。我们需要在未来维护32位和64位版本。


如果你的工作正常,你将只有维护版本,

将适用于32位和64位平台。这通常被称为

64位干净代码。

1.盲目地将所有长整数改为整数。但不是整数长。


不要盲目改变*任何东西。尝试理解*所有* * * b $ b * *每次*更改*

我们认为这可能会解决以下问题
(a)代码使用按位运算符编写,假设
long的大小为4将产生问题


修复此类代码。

(b)获取偏移量结构中的字段不使用
OFFSET宏会在结构长时间时产生问题


这样做首先是纯粹的愚蠢。如果你需要这样的

偏移量,offsetof()或指针算法是唯一的方法。

(c)通过使用
指针,如长i = 1; char a =((char *)& i)[0];
等.....


这不受32对64位问题的影响,但是可能会受到字节

订单问题的影响。从long切换到int购买什么都没有。并且你

真的想为此目的使用unsigned char。

2.检查所有返回long的库函数,如atol
并确保没有假设reaturn值为4个字节,编写代码。或者考虑将atol更改为atoi或simlar函数。


好​​多了,如果合理可能的话,在

代码中删除*所有* C类型大小的依赖项。

3.如果使用C风格的内存分配,则使用new内容。然后有bug的可能性。
long * ptr = malloc(4 * 2);
在32位编译中,上面的语句将分配8个字节的内存和ptr可以用作两个元素的数组。
但是在64位编译中,它将分配8个字节,并且数组中的元素数量为1。因此,如果编写代码
假设元素的数量为2,那么它将会中断。因此,应检查所有malloc的calloc和realloc。


的确,正确的解决办法是:


long * ptr = malloc(2 * sizeof * ptr);


这是正确的*无处不在*。

4.如果指针被转换为整数,则必须对其进行检查。
例如
int a = 10;
int * ptr =& a;
int b = reinterpret_cast< int>(a);
上面的代码将在64位编译中产生问题,因为
指针是8个字节,int是4个字节。因此必须将其改为
long b = reinterpret_cast< long>(a);
^^^^^^^^^^^^^^^^^^^^^^

这是无效的C语法,所以我不知道你是什么''正在谈论。

如果你需要将指针转换为整数,那么unsigned long类型是

32(ILP32)和64位的最佳选择( I32LP64)平台。

5.通过假设字段的大小而不使用OFFSET宏来获取结构字段的偏移量。


Deja vu(上面的第1b点)。

如果工会或班级的话,这个东西怎么办


联盟不需要它(所有成员都有偏移0)并且在C中没有类的


6. size_t是32位编译中的32位数量其中它在64位编译中增长到64。


为什么你的代码需要关注size_t的大小?

7.格式说明符应该在printfs和scanfs中检查
br /> long i =< some expression> ;;
printf("%d",i);
只要结果收敛就不会是一个大问题但是
当值非常大且超过整数限制时,将打印错误的值。




此代码已被破坏且纯粹的意外工作。如果我有长期类型

,则%d不是一个选项。 %ld将在32位和64位

平台上正常工作。


看起来你的代码在32位平台上严重破坏了

它运气/意外。一旦你修复它,如果你做得对,

它在32位和64位平台上同样运行良好,而不需要

单独版本。


如果您需要在32位和64位平台之间共享二进制文件,请支付

额外注意写入数据的定义

档。


Dan

-

Dan Pop

DESY Zeuthen, RZ集团

电子邮件: Da*****@ifh.de




" Dan Pop" <沓***** @ cern.ch>在消息中写道

news:cc ********** @ sunnews.cern.ch ...

In< 9b ***** *********************@posting.google.com>
mo ************ @ msn.com (Mohanasundaram)写道:


6。 size_t是32位编译中的32位数量,在64位编译中它增长到64位。



为什么你的代码要关心size_t的大小?



一些C / C ++ (原文如此)客户坚持认为必须有一种方法可以在结构中间埋没

size_t的东西,而不会填充或破坏平台之间的对齐
对齐,或任何编译哪个barf存储

int和size_t可以互换。当它出现时,它是一个可能的迹象,我应该回到那些没有C ++的项目中。



Mohanasundaram写道:

1.盲目地将所有长整数改为整数。但不是整数要长。
我们认为这可能会解决以下问题
(a)使用按位运算符编写的代码,假设
long的大小为4将产生问题
( b)不使用OFFSET宏来获取结构中字段的偏移量会在结构长时间时产生问题
(c)通过使用长指针打破长数据按字节顺序操作i = 1; char a =((char *)& i)[0];
等.....


如果您使用的是* NIX系统,请使用sys / types.h,并使用类似

u_int32_t,int32_t等等的东西。如果你在Windows上,请使用

的东西。

2.检查所有返回long的库函数,如atol
并确保没有编写代码,假设重新计算值为4个字节。或者考虑将atol更改为atoi或simlar函数。


修复我想说的库。

3.如果使用C风格内存分配,则使用new然后有bug的可能性。
long * ptr = malloc(4 * 2);
在32位编译中,上面的语句将分配8个字节的内存和ptr可以用作两个元素的数组。
但是在64位编译中,它将分配8个字节,并且数组中的元素数量为1。因此,如果编写代码
假设元素的数量为2,那么它将会中断。因此,应检查所有malloc的calloc和realloc。


使用malloc(sizeof(long)* 2)。

4.如果指针被转换为整数,那么它必须是
检查。
例如
int a = 10;
int * ptr =& a;
int b = reinterpret_cast< int>(a);
上面的代码会在64位编译中产生问题,因为
指针是8个字节,int是4个字节。因此必须将其改为
long b = reinterpret_cast< long>(a);


修复代码。铸造指向int的指针是设计中出现问题的一个标志。

5.通过假设字段大小而不使用OFFSET宏来获取结构字段的偏移量。这些东西如何在工会或类的情况下工作


编译器知道偏移量。由于你可以直接使用结构的成员

,我几乎没有理由使用它们。

6. size_t是32位编译中的32位数量,其中它增长<在64位编译中为64位。


size_t可以是32位平台中的64位变量。这些天很常见,因为在处理大文件时,偏移需要64位。


7.应该检查格式说明符,例如
在printfs和scanfs中
long i =< some expression> ;;
printf("%d",i);
只要结果收敛就不会是个大问题但是当值为i非常大且超过整数限制时,它将打印错误的值。


用一种类型替换long,表示你实际上是指b
的变量和长度。这样可以节省大量的麻烦,使代码更好地阅读。


非常感谢你的时间。

问候,Mohan。




Igmar


Hi All,

We are working on porting a product written in C and C++ from 32 bit
to 64 bit. We need to maintain both 32 bit and 64 bit versions in the
future. We took the 32 bit source code and copiled it using a 64 bit
compiler and fixed all the compilation warnings. Compilation went
through fine but the product breaks in lots of places. We understood
that porting a 32 bit code to 64 bit platform is not just a matter of
compilation. We have to handle the problems which will not be caught
by the compiler due to the change from ILP32 to LP64. So we are trying
to list out all the possible problems that might accour due to the
change from size of long and pointer from 4 bytes to 8 bytes with int
still being 4 bytes. We have listed out few possibilites of the places
where bugs might creep up. We want to validate the correctness of the
points and would like to add more in to this list. Please help us.

1. Change all the long to integers blindly. But not integers to long.
We think this might solve the following problems
(a) Code written using bitwise operators assuming that the size of
long is 4 will create problems
(b) Getting the offsets of the fields in structures by not using
OFFSET macro will create problems when the structe has longs
(c) Manipulating the long data bytewise by breaking them using
pointers like long i = 1; char a = ((char *)&i)[0];
etc.....

2. Check for all the library functions which returns long, like atol
and make sure no code is written assuming that the reaturn value
is of 4 bytes. Or consider changing atol to atoi or simlar functions.

3. If C style memory allocation is used insted of "new" then there are
possibility for bugs.
long *ptr = malloc(4*2);
in 32 bit compilation the above statement will allocate 8 bytes of
memory and ptr can be used as an array of two elements.
But in 64 bit compilation it will allocate 8 bytes and the number of
elements in the array is one. So if code is written
assuming that the number of elements is two then it will break. So
all "malloc"s "calloc"s and "realloc"s should be checked.

4. If the pointers are casted to integers anywhere it has to be
checked.
For example
int a = 10;
int *ptr = &a;
int b = reinterpret_cast<int>(a);
The above code will crete problems in 64 bit compilation since
pointer is 8 bytes and int is 4 bytes. So it has to be
changed to
long b = reinterpret_cast<long>(a);

5. Getting the offsets of the structure fields by assuming the size of
the fields and not using OFFSET macro. How does this stuff
work in case of unions or classes

6. size_t is a 32 bit quantity in 32 bit compilation wherein it grows
to 64 in 64 bit compilation.

7. The format specifiers should be checked for example
in printfs and scanfs
long i = <some expression>;
printf("%d",i);
will not be a big problem as far as the result is converned but it
will print wrong values when the value is i is very
big and exceeds the limit of integer.

Thanks a lot for your time.

Regards,
Mohan.

解决方案

In <9b**************************@posting.google.com > mo************@msn.com (Mohanasundaram) writes:

We are working on porting a product written in C and C++ from 32 bit
to 64 bit. We need to maintain both 32 bit and 64 bit versions in the
future.
If you do your job right, you will have only version to maintain, that
will work on both 32 and 64-bit platforms. This is usually called
64-bit clean code.
1. Change all the long to integers blindly. But not integers to long.
Don''t change *anything* blindly. Try to understand *all* the implications
of *each and every* change you make.
We think this might solve the following problems
(a) Code written using bitwise operators assuming that the size of
long is 4 will create problems
Fix such code instead.
(b) Getting the offsets of the fields in structures by not using
OFFSET macro will create problems when the structe has longs
Doing that is sheer stupidity in the first place. If you need such
offsets, offsetof() or pointer arithmetic are the ONLY ways to go.
(c) Manipulating the long data bytewise by breaking them using
pointers like long i = 1; char a = ((char *)&i)[0];
etc.....
This is not affected by 32 vs 64 bit issues, but may be affected by byte
order issues. Switching from long to int buys you nothing. And you
really want to use unsigned char for this purpose.
2. Check for all the library functions which returns long, like atol
and make sure no code is written assuming that the reaturn value
is of 4 bytes. Or consider changing atol to atoi or simlar functions.
Much better, remove *all* the dependencies of the C types sizes in the
code, if reasonably possible.
3. If C style memory allocation is used insted of "new" then there are
possibility for bugs.
long *ptr = malloc(4*2);
in 32 bit compilation the above statement will allocate 8 bytes of
memory and ptr can be used as an array of two elements.
But in 64 bit compilation it will allocate 8 bytes and the number of
elements in the array is one. So if code is written
assuming that the number of elements is two then it will break. So
all "malloc"s "calloc"s and "realloc"s should be checked.
Indeed, and the proper fix is:

long *ptr = malloc(2 * sizeof *ptr);

which is correct *everywhere*.
4. If the pointers are casted to integers anywhere it has to be
checked.
For example
int a = 10;
int *ptr = &a;
int b = reinterpret_cast<int>(a);
The above code will crete problems in 64 bit compilation since
pointer is 8 bytes and int is 4 bytes. So it has to be
changed to
long b = reinterpret_cast<long>(a); ^^^^^^^^^^^^^^^^^^^^^^
This is not valid C syntax, so I don''t know what you''re talking about.
If you need to convert pointers to integers, the type unsigned long is
the best choice on both 32 (ILP32) and 64-bit (I32LP64) platforms.
5. Getting the offsets of the structure fields by assuming the size of
the fields and not using OFFSET macro.
Deja vu (point 1b above).
How does this stuff work in case of unions or classes
It is not needed for unions (all members have offset 0) and there are
no classes in C.
6. size_t is a 32 bit quantity in 32 bit compilation wherein it grows
to 64 in 64 bit compilation.
Why should your code care about the size of size_t?
7. The format specifiers should be checked for example
in printfs and scanfs
long i = <some expression>;
printf("%d",i);
will not be a big problem as far as the result is converned but it
will print wrong values when the value is i is very
big and exceeds the limit of integer.



This code is already broken and it works by pure accident. If i has type
long, %d is NOT an option. %ld will correctly work on both 32 and 64-bit
platforms.

It looks like your code was severely broken even on 32-bit platforms and
it worked by luck/accident. Once you fix it, if you do the job right,
it will work equally well on both 32 and 64-bit platforms, without needing
separate versions.

If you need to share binary files between 32 and 64-bit platforms, pay
extra attention to the definition of the data that gets written into the
files.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de



"Dan Pop" <Da*****@cern.ch> wrote in message
news:cc**********@sunnews.cern.ch...

In <9b**************************@posting.google.com > mo************@msn.com (Mohanasundaram) writes:


6. size_t is a 32 bit quantity in 32 bit compilation wherein it grows
to 64 in 64 bit compilation.



Why should your code care about the size of size_t?


Some "C/C++" (sic) customers are adamant that there has to be a way to bury
size_t stuff in the middle of a struct without padding or breaking
alignments between platforms, or that any compiler which barfs at storing
int and size_t interchangeably is broken. When that comes up, it''s a
probable sign that I should go back to projects which don''t have C++ in
them.


Mohanasundaram wrote:

1. Change all the long to integers blindly. But not integers to long.
We think this might solve the following problems
(a) Code written using bitwise operators assuming that the size of
long is 4 will create problems
(b) Getting the offsets of the fields in structures by not using
OFFSET macro will create problems when the structe has longs
(c) Manipulating the long data bytewise by breaking them using
pointers like long i = 1; char a = ((char *)&i)[0];
etc.....
If you''re on a *NIX system, use sys/types.h, and use things like
u_int32_t, int32_t, etc, etc. If you''re on Windows, use something that
looks like it.
2. Check for all the library functions which returns long, like atol
and make sure no code is written assuming that the reaturn value
is of 4 bytes. Or consider changing atol to atoi or simlar functions.
Fix the library I would say.
3. If C style memory allocation is used insted of "new" then there are
possibility for bugs.
long *ptr = malloc(4*2);
in 32 bit compilation the above statement will allocate 8 bytes of
memory and ptr can be used as an array of two elements.
But in 64 bit compilation it will allocate 8 bytes and the number of
elements in the array is one. So if code is written
assuming that the number of elements is two then it will break. So
all "malloc"s "calloc"s and "realloc"s should be checked.
use malloc(sizeof(long) * 2) for that.
4. If the pointers are casted to integers anywhere it has to be
checked.
For example
int a = 10;
int *ptr = &a;
int b = reinterpret_cast<int>(a);
The above code will crete problems in 64 bit compilation since
pointer is 8 bytes and int is 4 bytes. So it has to be
changed to
long b = reinterpret_cast<long>(a);
Fix the code. Casting pointers to ints is a sign of problems in the design.
5. Getting the offsets of the structure fields by assuming the size of
the fields and not using OFFSET macro. How does this stuff
work in case of unions or classes
The compiler knows the offset. Since you can use members of structs
directly, I hardly see a reason to use them.
6. size_t is a 32 bit quantity in 32 bit compilation wherein it grows
to 64 in 64 bit compilation.
size_t can be a 64 bits variable in 32 bits platforms. It is common
these days, since offsets need 64 bits when dealing with large files.

7. The format specifiers should be checked for example
in printfs and scanfs
long i = <some expression>;
printf("%d",i);
will not be a big problem as far as the result is converned but it
will print wrong values when the value is i is very
big and exceeds the limit of integer.
Replace long by an type that indicates what variable and length you
actually mean. That saves tons of headaches, an make the code better to
read.

Thanks a lot for your time.

Regards,
Mohan.



Igmar


这篇关于64位移植的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆