Cでの32ビットアプリケーションから64ビットアプリケーションへの変換
質問
現在、Cで32ビットアプリケーションを64ビットアプリケーションに変換しています。このアプリケーションは、現在x86アーキテクチャ(Windows、osx、Unix、Linux)で動作しています。そのため、コーディングを開始する前に、アプリケーションの変換中に何を考慮する必要があるかを知りたいと思いました。
解決
- 誰が書いたのかを調べます。彼らはばかですか?彼らは数年前からあなたですか?質問してもらえますか?彼らは複数のプラットフォームとシステムの存在に精通していますか? プログラムの作者の考え方を知ることは、問題に遭遇したときに問題を理解するのに役立ちます。
- 64ビットのマシン/ビルド環境を稼働させます。
- longをintに置き換えます。
LONG
はlong
ではないことに完全に注意してください。 - キャスト
(int)&x
を置き換え、intptr_t
で入力し、(unsigned int)&x
をuintptr_t
で入力
- 構造体を
char*
にキャストすることに依存するものはすべて、それを使用してポインター演算を行います。 - \ <!> lt; 4 \ <!> gt;の正規表現検索
4 = sizeof(void*)
と仮定した場合
- 我慢してください。問題が見つかったら、同じ問題が存在する場合は別の場所を探し、マクロで解決策をラップします。
-
#ifdef RUN64
などを使用しないでください。 128ビットプラットフォームが流行した場合は、後悔します。 - すべての変更をカプセル化して、プログラムの他の場所での移植性の違いを隠蔽する中央集中マクロを作成します。
- カバレッジテスターを使用して、すべてをカバーしたことを確認します(適切な場合)
編集は、コメントで示唆されているように<=>メモを追加しました。
他のヒント
まだ言及されていない潜在的な問題の1つは、アプリがディスクからバイナリデータを読み書きする場合(たとえば、fread
を使用して構造体の配列を読み取る)、非常に慎重にチェックしなければならず、おそらく2つのリーダー:レガシーファイル用と64ビットファイル用。または、uint32_t
ヘッダーファイルから<stdint.h>
などのタイプを使用する場合は、構造体をビットごとに互換性があるように再定義できます。いずれにせよ、バイナリI / O には注意が必要です。
これは、アプリケーションとコーディング方法によって異なります。一部のコードは64ビットコンパイラで再コンパイルするだけで機能しますが、通常、移植性を念頭に置いてコードが設計されている場合にのみ発生します。
コードにネイティブ型とポインターのサイズに関する多くの仮定がある場合、ビットパッキングハッキングが多い場合、またはバイト指定プロトコルを使用して外部プロセスと通信するが、そのサイズに関するいくつかの仮定を使用する場合ネイティブ型の場合は、クリーンコンパイルを取得するために、ある程度の作業が必要になる場合があります。
ほとんどすべてのキャストとコンパイラの警告は、チェックアウトが必要な赤旗です。コードが<!> quot; warning clean <!> quotではなかった場合;それから始めることは、多くの作業が必要になる可能性があることを示しています。
値に正しいタイプを使用した場合-例size_t
、ptrdiff_t
、uintptr_t
、必要に応じてstdint.h
からの固定サイズのint型-値のサイズをハードコーディングしなかった場合、コードはそのまま使用できます。
64ビットに切り替えるときに直面する主な問題は、ポインターのサイズが異なることです(32ではなく64ビット-duh)。プラットフォームによっては、整数のサイズとlongのサイズも異なる場合があります。
なぜこれが問題なのですか?コードでは、sizeof(int)== sizeof(void *)と仮定しない限り、そうではありません。これにより、厄介なポインターバグが発生する可能性があります。
まあ、基本的に、変更の数はかなり少ないですが、アプリケーションが最初からある程度移植性があるように注意深く書かれていなければ、それは依然として大きなタスクです。
主な違いは、ポインターが64ビット幅であることです。ただし、他のほとんどのデータ型は変更されていません。 intは依然として32ビットであり、longもおそらく32ビットです。したがって、コードがintとポインターの間でキャストすると、それは壊れます。同様に、メンバーへの特定のオフセットに依存する構造体または類似物は、他のメンバーが大きくなる可能性があるために壊れる可能性があり、オフセットを変更します。
もちろん、あなたのコードはこれらのトリックに最初から依存するべきではないので、理想的な世界では、これはまったく問題ではなく、単純に再コンパイルすればすべてが機能します。しかし、あなたはおそらく理想的な世界に住んでいないでしょう;;)
Cでの32ビットと64ビットのプログラミングの2つの大きな違いは、sizeof(void *)とsizeof(long)です。主な問題は、ほとんどのUnixシステムが64ビット長を定義するI32LP64標準を使用し、Win64が32ビット長を定義するIL32LLP64標準を使用することです。クロスプラットフォームコンパイルをサポートする必要がある場合は、32ビットおよび64ビット整数のアーキテクチャベースのtypedefのセットを使用して、すべてのコードが一貫して動作するようにすることができます。これは、C99標準の一部としてstdint.hの一部として提供されます。 C99コンパイラを使用していない場合は、独自の同等物をロールする必要がある場合があります
他の箇所で述べたように、変換の主な関心事は、sizeof(int)== sizeof(long)== sizeof(void *)を前提とするコード、ディスクに書き込まれたデータをサポートするコード、およびクロスプラットフォームIPCのコードです。
この背後にある歴史をよく確認するには、この記事 ACMキューから。
すでに多くの良い答えがあります。
Gimpel Lint の使用を検討してください。問題のある構造のタイプを正確に指摘できます。あなたの経験が私のようなものである場合、32/64ビットポートとは関係のないシステムの多くのバグも表示されます。