アプリ版:「スタンプのみでお礼する」機能のリリースについて

ファイル読み込み時に読み込んだデータサイズと、それを格納するストラクタのsizeofで取得したサイズが異なる為エラーになってしまいます。

実際のデータ→10バイト
構造体→WORD、DWORD、DWORDの10バイト
なのですが、

blRet = ReadFile(hNDFile[bFile], cpReadData, sizeof(構造体),&outFileSize, 0 );

とすると、構造体のsizeofの値が12になる為関数は戻り値1(エラー)で返ってきてしまいます。
取得した値自体は問題ないのですが。。

逆にこの問題を解決しようとして構造体宣言の部分を#pragma pack(push , 1)で囲うと、sizeof(構造体)の値は10バイトとなり、readfile関数は正常に終わるのですが、読み取ったデータの値が想定していないものになってしまいます。

何がおかしいかわからず困っています。。

A 回答 (7件)

それは当たり前です。


構造体が、WORD、DWORD、DWORDだとしたら実際のメモリ上では、WORD、2バイトの余白、DWORD、DWORDと配置されています。
10バイトしか読み込みしないと最後のDWORDの途中までしか読み込んでいません。リトルエンディアンだと起きる大きな勘違いで、最後のDWORDの値が65536を超えているとちゃんと読めないはずです。

#pragma pack(push , 1)
でちゃんと読めないのは、もともと出力されているはファイルが
#pragma pack(push , 1)
で出力されていないからではないですか?

解決法は、
DWORD、DWORD、WORD
で入出力を統一することです。

この回答への補足

回答ありがとうございます。

実際のデータはサイズはバイナリで10バイトなのです。
※データのアライメントは1バイト並びだそうです。

ですのでDWARDで統一すると12バイトになりますよね?
そうするとReadFile関数で該当ファイルを読み込んだ場合、実際の読み込んだファイルサイズが10バイト、sizeof(構造体)のサイズが12バイトとなり、エラーになってしまうのです。。
エラーといってもReadFileの戻り値に1が帰ってくるだけで、読み込んだ値は正しく取得出来ているようです。

構造体のサイズをsizeof(構造体)ではなく、10と直に入力すると一番希望通りの処理になるのですが、他のファイル読み込みでも使用する関数の為無理です。。

初心者ですので変な事を言っていたらすいません。。

補足日時:2007/07/27 19:52
    • good
    • 0

★追記。


・データのアライメントは1バイトでもプログラムが1バイトではないので
 データとプログラムの両方のアライメントを合わせる必要があります。
・データのアライメントは1バイトなのでプログラムを作り直せば良いです。
 コンパイルのオプション設定を回答 No.6 を参考に変更してコンパイルを
 やり直せばよい。これで ReadFile() の戻り値と sizeof(構造体)のバイト数が
 一致します。
・以上。
    • good
    • 0
この回答へのお礼

沢山の回答ありがとうございました。
結局もらったデータが仕様書と間違っていた事が判明しました。
そりゃあ矛盾が生じるわけですね。。
為になるアドバイス助かりました。

ですがいろいろ勉強する良い機会になりました。
ありがとうございました。

お礼日時:2007/08/01 14:07

★もう一つの方法


・コンパイル・オプションを変更する方法もある。
 構造体の場合は1、2、4、8、16バイトにアライメントされます。
 処理系により初期値が違いますが BCC では1バイトに VC 系では4バイトに
 なっていたりします。デフォルトですのでオプションで変更できます。
・処理系(コンパイラ)が分かりませんが VC ならプロジェクトのプロパティから
 『C/C++』→『コード生成』→『構造体のアライメント』の設定を変更します。
 変更する時『既定値』から『1バイト /Zp1』にします。
 他の処理系でもオプションで変更できます。
・構造体のアライメントを1バイトに変更すると正しくなります。
 ただし一度作成したデータファイルはもう一度作り直す必要があります。
・以上。
    • good
    • 0

そうですね。


対策は2つあります。
(1)プログラムは、#pragma pack(push,1)なしにする。
ファイルを作るプログラムは、出力サイズを単純に10としないで、sizeof(構造体)を使う。
(2)#pragma pack(push,1)を使うなら、ファイル作成とファイル入力の両方で使わないとだめです。
    • good
    • 0

回答者#1&#3です。


やはり私の思った通りのデータでした。
19 22 00 00 01 00 00 00 0A 00
をデータに分解すると
[19 22] WORD 0x2219で10進で8729。
[00 00] WORD。たぶん2バイトの余白。
[01 00 00 00] DWORD 0x00000001で10進で1。
[0A 00] WORD 0x000Aで10進で10。
となり最後がDWORDで4バイトのはずがWORDで2バイトしかありません。
ですので、#1の回答の通りにすべきです。
今の段階では、読み込みべきデータファイルが破損している状態ですね。

ちなみに#pragma pack(push , 1)で読み込むと、
[19 22] WORD 0x2219で10進で8729。
[00 00 01 00] DWORD 0x00010000で10進で65536。
[00 00 0A 00] DWORD 0x000A0000で10進で655360。
となるはずですが?
もしならないなら、別に他の問題があるのかも。
    • good
    • 0

私もデータが見たいですね。


ファイルの内容を16進ダンプしたものが見たいです。
バイナリエディタなどで表示して、コピペしてください。
もちろん、WORD、DWORD、DWORに入っているはずの値もほしいです。
    • good
    • 0

実際のデータのWORD、DWORD、DWORDの値と、プログラムで読み込んだデータをprintfしたものを教えてください。

この回答への補足

バイナリエディタで開いたところ
19 22 00 00 01 00 00 00 0A 00
です。

WORD→正確な値は不明
DWORD→1
DWORD→10
になっていれば正しい値です。

プログラムで読み込んだ場合、pragmaを付けると
1→256
10→65535?になってしまいます。

pragmaを付けないと値は正常に取得出来るのですが、Readfile関数でエラーが返ってきてしまいます。。

補足日時:2007/07/27 20:57
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!