質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • TCP

    188questions

    TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

  • Visual C++

    145questions

    Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

構造体メンバの配列へのファイル読み込みについて

受付中

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 1,407

cfu0987_APV

score 9

TCP通信における構造体メンバの配列へのファイル読み込みについて質問します。
TCPでビットマップと数値を送信するプログラムを作りました。
ネットを参考に下のプログラムを作り実行した結果、①の返り値は2500018を返しますが、受け取ったビットマップファイルには何も入っていませんでした(ファイルサイズ2.5M程度)。
そこで、②の返り値を見ると'0'でした。また、③の値は'19'でした。

〇質問
1.④で2.5Mのビットマップを読み込ませるために構造体(bmpfile[])のサイズを変えているのですが、この方法ではサイズの変更はできないのでしょうか。
2.もし質問1の方法が正しいとしたら、なぜ③でサイズ変更前の値が返ってくるのでしょうか。
3.①及び②の関数(send, fread)への引数への代入はこれで正しいでしょうか。

〇環境
  OS:windouws7(SP1) 32ビットOS
   開発:visual C++(2008)
 メモリ:4GB
 CPU:2.5GHz 

〇プログラム
★struct.h

struct BMP_PIC{
  unsigned short    marker;//①マーカー
  unsigned long    size;//②データバイト数
  unsigned short tp;//③ヘッダ種別
  unsigned short  no;//④ヘッダ番号
  float        x;//数値1
  float        y;//数値2
  unsigned char    bmpfile[1];//ビットマップ用の配列(2.5Mを読み込ませる)
 } ;

★tTCP.cpp: 

FILE *BMPFP;
 #define BMPTEST ".\\pic.bmp"

BMPFP = fopen(BMPTEST, "rb");
struct BMP_PIC *m_BmpPic;
fpos_t sz;
fseek(BMPFP, 0, SEEK_END);
fgetpos(BMPFP, &sz);

m_BmpPic = (struct BMP_PIC *)malloc(sizeof(struct BMP_PIC) - 1 + sz);//④

m_BmpPic.marker = 0xABCD;
m_BmpPic.size = sz + 8;//・・・実際のデータ(ビットマップ + 数値1 + 数値2)サイズを指定する。
m_BmpPic.type = 0;
m_BmpPic.no = 0;
m_BmpPic.x = 1000;
m_BmpPic.y = 2000;

sizeof(*m_BmpPic);//③
fread(m_BmpPic->bmpfile, 1, sz, BMPFP);//②
send(s1, reinterpret_cast<const char*>(m_BmpPic), sz + 18, 0);//①

free(m_BmpPic);

fclose(BMPFP);
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

0

こんにちは。

1.④で2.5Mのビットマップを読み込ませるために構造体(bmpfile[])のサイズを変えているのですが、この方法ではサイズの変更はできないのでしょうか。 

この方法で実質的なサイズ変更は可能です。といいますか、昔からC言語で良く使われるテクニックですね。

2.もし質問1の方法が正しいとしたら、なぜ③でサイズ変更前の値が返ってくるのでしょうか。 

sizeof()演算子はコンパイル時に値が計算されます。
sizeof(*m_BmpPic);と記述した場合、m_BmpPicが指すメモリ領域のサイズではなく、*mBmpPicの型(この場合、BMP_PIC)のサイズになります。

3.①及び②の関数(send, fread)への引数への代入はこれで正しいでしょうか。

②は正しいように見えます。①は18という数字の意味にもよりますが、もしそれが、sizeof(struct BMP_PIC) - 1を意味している場合は期待通りの値になっていない可能性があります。
多くの処理系ではメンバ変数を配置する際、アクセスが高速になる位置に配置することが多いです。
そのような処理系では、unsigned longが4バイトの場合、4バイト境界(アドレスの下位2ビットが0)に配置されます。unsigned shortが2バイトだった場合、先頭のmarkerと次のsizeの間に2バイトのパディングが入る場合が多いです。アライメントと呼ばれます。
mallocの時と同様な計算式で計算されることをお勧めします。

①の返り値は2500018を返しますが、受け取ったビットマップファイルには何も入っていませんでした

上記ミスでは、恐らく最後の2バイトが欠けるだけですので、何も入っていないという状態にはならなさそうな印象です。小さい画像ファイルなら受け取れましたでしょうか?

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/20 00:30

    あ、そういえばsizeof(struct BMP_PIC) - 1も期待通りの値にはなってないかも知れません。期待値より3大きい可能性があります。一度、確認されると良いと思います。

    下記が参考になります。
    http://www5d.biglobe.ne.jp/~noocyte/Programming/Alignment.html#sizeofAndAlignment

    キャンセル

  • 2016/04/20 21:35 編集

    ④の一つ前の行で”sizeof(struct BMP_PIC) - 1”の値を見ると"18"でこれは期待通りでした。
    試しに50kバイトのビットマップ((H)240x(V)72, 色コード:ED1C24)を送信してみましたが、やはり正常には送れませんでした。受け取ったファイルをバイナリで開いてみるとヘッダ部含め全て"ADBA0DF0"で埋め尽くされていました。なので、読み込み(fread)に問題があるのでしょうか?

    キャンセル

  • 2016/04/20 21:50

    > ④の一つ前の行で”sizeof(struct BMP_PIC) - 1”の値を見ると"18"でこれは期待通りでした。

    ということは、#pragma pack(1)されているのですね。
    性能は若干落ちますが、有効範囲を必要最小限にしていれば問題ないです。

    > 読み込み(fread)に問題があるのでしょうか?

    fread直後のデータを見てみれば分かるのでは?
    しかし、freadしていないヘッダまで化けているのであれば、freadの可能性は低いと思います。
    例えば、データを0x55等で埋めて送ってみて、受信側で受け取れているのか確認するのも手と思います。
    受け取れていないようでしたら、sendできているのか、recvできているのか?どちらかを切り分けるべきでしょう。そのような時はWireSharkが便利です。無償で使えるパケット・キャプチャです。http://beginners-network.com/wireshark.html

    キャンセル

  • 2016/04/21 20:07

    試しに0x55で全て書き込んだファイルを送った結果、受信ファイルは"ADBA0DF0"で埋められていました。また、②の後にfwrite(m_BmpPic->bmpfile, 1, sz, FP)を実行し作成したファイルも"ADBA0DF0"で埋められていました。なので、freadに問題があるように思えますが、これ以上どうしたらいいかがわかりません。

    キャンセル

  • 2016/04/21 21:48

    そのような時は、経験上ほぼ100%何か大きな単純な間違いをしています。
    落ち着いて1つ1つ確認しましょう。

    ・②の直後でダンプしてみて"ADBA0DF0"で埋められている。
    ・その後で0x55でてデータを送ったのに受信側でも"ADBA0DF0"で埋められている。

    この2つは独立な事象なので同じデータで埋められるというこは本質的にありません。
    ということは、ダンプ方法をミスしている可能性が高いと思います。

    どうしても判らないようでしたら、データを読んでダンプする部分なら、ソースをここに上げることが可能と思います。簡単にビルド/実行できる最小のソースとし、問題が再現することを確認した上で、ここで再度質問されると良いと思います。

    キャンセル

0

szを採取するために fseekでファイルの終端に移動していますが
freadする前に fseekでファイルの先頭に戻さないといけないと思いますよ ・・・

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • TCP

    188questions

    TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

  • Visual C++

    145questions

    Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。