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

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

ただいまの
回答率

91.37%

  • C

    2524questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    2409questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • Visual Studio

    1202questions

    Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

ハンドルされない例外、書き込み中にアクセス違反。タイマー関数を使いビットマップ形式で球を描画したいのだが、描画途中で描画されなくなる

受付中

回答 3

投稿 2017/12/07 00:30 ・編集 2017/12/08 18:59

  • 評価
  • クリップ 0
  • VIEW 147

TRON1216.

score 3

.bat形式のあるデータ(球体の半径など)を読み取り、タイマー関数を用いてビットマップ形式で描画しようとしています。ビルドも無事にでき、実行したのですが、なぜか途中でエラーが起きます。半径の全データ数は約4600個あり、150msごとに再描画を繰り返す感じです。エラーのタイミングはさまざまで、2422番目のデータでストップしたり、3355番目でストップなどです。デバッグして調べたところ、全データの読み込みはちゃんとできていて、インフォヘッダーで書いた中身(g_img)が0になっていました。また、ハンドルされない例外が0x00365F6E で発生しました。や、書き込み中にアクセス違反が発生しました。といった文章がでてきました。メモリの解放のタイミングがおかしいのでしょうか?もしおかしければ解放のタイミングを知りたいです。また、この原因がメモリの解放以外にありそうでしたらアドバイスいただきたいです。メモリの解放のタイミング以外で考えると、BITMAPINFOHEADERもしくはCreatDIBitmap()のどこかがおかしいのだと考えています。ですが改善策がでてきません。よろしくお願いいたします。開発環境は、Visual Studio 2015 C++です。なお、まだ初心者なので、説明不足や知識不足、理解不足があるかもしれません。ご了承ください。下記に、描画するコードを載せておきます。

#include <math.h>
#define ID_MYTIMER 1




typedef struct{
    HINSTANCE hi0;
    HWND hwin7;
    BYTE *lpBmpData;
    BITMAPINFOHEADER bmp_ih;
    char *fname;
    int fsize;
} IMG;

IMG g_img;

LRESULT CALLBACK WndProc_bitmap( HWND hWnd_bitmap, UINT msg, WPARAM wp, LPARAM lp )
{

    PAINTSTRUCT ps;
    HDC hdc, hdc_mem;
    HBITMAP hBmp;
    float x,y,z,r;
    int a, b, ab;
    float lam1,lam2,lam3;

    g_img.bmp_ih.biSize = sizeof(BITMAPINFOHEADER);
    g_img.bmp_ih.biWidth = 659/*674*/;
    g_img.bmp_ih.biHeight = -494/*532*/;
    g_img.bmp_ih.biPlanes = 1;
    g_img.bmp_ih.biBitCount = 32;
    g_img.bmp_ih.biCompression = BI_RGB;
    g_img.bmp_ih.biSizeImage = 659/*674*/ * 494/*532*/ * 4;
    g_img.bmp_ih.biXPelsPerMeter = 3704;
    g_img.bmp_ih.biYPelsPerMeter = 3704;
    g_img.bmp_ih.biClrUsed = 0;
    g_img.bmp_ih.biClrImportant = 0;

    g_img.lpBmpData = (BYTE *)malloc(659/*674*/*494/*532*/*4);








    switch (msg) {

    case WM_CREATE: //ウインドウが生成されたときに1度だけ通過
        //時間割り込みの発生タイミングを設定
        SetTimer(hWnd_bitmap, ID_MYTIMER, 150, NULL);
        break;

    case WM_TIMER:
       if (wp != ID_MYTIMER)
           return (DefWindowProc(hWnd_bitmap, msg, wp, lp));
        k +=1;
        InvalidateRect(hWnd_bitmap, NULL, FALSE);

        break;

    case WM_PAINT:
        hdc = BeginPaint(hWnd_bitmap, &ps);
        hdc_mem = CreateCompatibleDC( hdc );
        q = 0;
        p = 0;
        for ( a = 0; a < 494/*532*/; a++){
            for( b = 0; b < 659/*674*/; b++){
                ab = a*(659/*674*/*4) + b*4; //始めの項が行数、次の項が左から何ビット目かを表す。(blueの位置を決めている)

                if((b-329.5)*(b-329.5)+(a-494)*(a-494) <= (s[k]/4*1000000*329.5+0.5)*(s[k]/4*1000000*329.5+0.5)){
                    p = p+1.0; //円の内側のピクセル数の合計
                    x = b-329.5;
                    y = 494-a;
                    z = sqrtf(-(x*x)-(y*y)+(s[k]/4*1000000*329.5+0.5)*(s[k]/4*1000000*329.5+0.5));
                    r = sqrtf(x*x + y*y + z*z);


                        lam1 = (x*XSUNm_3[k] + y*YSUNm_3[k] + z*ZSUNm_3[k])/(r*SUN_MOON[k]); //太陽の方向との内積
                        lam2 = (x*XEARTHm_3[k] + y*YEARTHm_3[k] + z*ZEARTHm_3[k])/(r*EARTH_MOON[k]); //地球の方向との内積
                        lam3 = (x*XEQLm_3[k] + y*YEQLm_3[k] + z*ZEQLm_3[k])/(r*EQL_MOON[k]); //EQLの方向との内積

                         /*g_img.lpBmpData[ab] = 179*lam3;
                         g_img.lpBmpData[ab+1] = 179*lam3;
                         g_img.lpBmpData[ab+2] = 179*lam3;
                         g_img.lpBmpData[ab+3] = 0;*/



                        if(lam2>0){
                         g_img.lpBmpData[ab] = 230*lam2;
                         g_img.lpBmpData[ab+1] = 216*lam2;
                         g_img.lpBmpData[ab+2] = 0;
                         g_img.lpBmpData[ab+3] = 0;

                       }

                        if(lam1>0){
                         g_img.lpBmpData[ab] = 0;
                         g_img.lpBmpData[ab+1] = 255*lam1;
                         g_img.lpBmpData[ab+2] = 255*lam1;
                         g_img.lpBmpData[ab+3] = 0;
                       }

                        if(!(lam1>=0 || lam2>=0) ){
                         g_img.lpBmpData[ab] = 179*lam3;
                         g_img.lpBmpData[ab+1] = 179*lam3;
                         g_img.lpBmpData[ab+2] = 179*lam3;
                         g_img.lpBmpData[ab+3] = 0;

                         q = q+1;                
                        }

                 if(494 < (s[k]/4*1000000*329.5+0.5))
                     ok = q*100/325546;

                 if(494 >= (s[k]/4*1000000*329.5+0.5))
                    ok = q*100/p/*(M_PI* (s[k]/4*1000000*329.5+0.5)*(s[k]/4*1000000*329.5+0.5)/2)*/;

                }

                   // else{
                if((b-329.5)*(b-329.5)+(a-494)*(a-494) > (s[k]/4*1000000*329.5+0.5)*(s[k]/4*1000000*329.5+0.5)){
                        g_img.lpBmpData[ab] = 0;
                        g_img.lpBmpData[ab+1] = 0;
                        g_img.lpBmpData[ab+2] = 0;
                        g_img.lpBmpData[ab+3] = 0;
                       }


            }

        }

        hBmp = CreateDIBitmap(hdc, &(g_img.bmp_ih), CBM_INIT, g_img.lpBmpData, (BITMAPINFO *)(&(g_img.bmp_ih)), DIB_RGB_COLORS);
        free(g_img.lpBmpData);
        SelectObject(hdc_mem, hBmp);
        SetStretchBltMode(hdc, COLORONCOLOR);
        StretchBlt(hdc, 0, 0, 659/*674*/, 494/*532*/, hdc_mem, 0, 0, 659/*674*/, 494/*532*/, SRCCOPY);
        DeleteDC( hdc );
        DeleteDC( hdc_mem );
        DeleteObject( hBmp );
        EndPaint(hWnd_bitmap, &ps);
        ReleaseDC( hWnd_bitmap, hdc );

        break;
mode_edit編集
arrow_downward自己解決方法を記入する
attachment(0)
thumb_up(0)
低評価 (0)
delete
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

+1

これが原因かどうかわかりませんが、プログラム的にまずいなと思うところを書いておきます。

WM_TIMERメッセージの処理で、k += 1し、そのkはWM_PAINTの中でs[k]として配列のインデックスとして使用されてますが、このままだとkはどこまでも+1されてしまうので、ストッパーの処理が必要です。そうしないと配列をオーバーしてアクセスしてしまう可能性があります。

また、kをインクリメントする処理はWM_TIMERの中ではなく、WM_PAINTのなかでインクリメントして、その中でkの値が配列をオーバーしないように処理した方がいいと思います。そのほうが安全です。

投稿 2017/12/07 17:53

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/12/07 22:53

    回答ありがとうございます。言いたいことはわかりました。150msごとにデータを順に再描画していこうと考えると、これしか思いつきませんでした。具体的にはどうすればいいのか見当がつきません。よろしければコードで教えていただけると幸いです。

    キャンセル

  • 2017/12/08 16:44

    WM_TIMERでは、InvalidateRectだけやって、k++はしない。
    WM_PAINTの先頭でk++をやって、配列sの添字の上限でリミットを掛けておけば、配列のオーバーアクセスはなくなります。配列sサイズをARRAY_SIZEとすると、
    if (++k > ARRAY_SIZE) k = ARRAY_SIZE - 1;
    の様な感じですね。

    キャンセル

  • 2017/12/08 17:36

    丁寧な返答ありがとうございます。やってみます!!

    キャンセル

  • 2017/12/08 18:23

    やりましたが、やはり同様の結果がおきました。あと、デバッグして調べましたが、毎回オーバーアクセスする前でプログラムが停止していました。おそらくg_imgがおかしいのだと思います。その中身がプログラム停止時に毎回0になっています。

    キャンセル

  • 2017/12/11 17:25

    これ、よく見たらswitch文の外で
    g_img.lpBmpData = (BYTE *)malloc(659/*674*/*494/*532*/*4);
    で、確保してますけど、これはまずいですよ。
    つまり、WM_PAINTのメッセージの時だけ(case WM_PAINTの内側で)確保するようにしないと。もっと言えば、g_imgの各メンバーの初期化は、WM_PAINT処理の頭でやらないといけない、ということです。

    キャンセル

  • 2017/12/12 02:25

    すいませんいま回答みました。ご指摘ありがとうございます。直して実行してみます。

    キャンセル

  • 2017/12/12 02:54

    WM_PAINTの中に入れるとビルドはできるのですが実行した瞬間プログラムが停止しました、、。

    キャンセル

0

ざっとコードを見た限りなので見落としがあるかもしれませんが、

    hBmp = CreateDIBitmap(hdc, &(g_img.bmp_ih), CBM_INIT, g_img.lpBmpData, (BITMAPINFO *)(&(g_img.bmp_ih)), DIB_RGB_COLORS);


この部分、BITMAPINFOHEADERをBITMAPINFOにキャストして使っていますね。BITMAPINFO構造体は

typedef struct tagBITMAPINFO {  
    BITMAPINFOHEADER bmiHeader;  
    RGBQUAD bmiColors[1];  
} BITMAPINFO;  


なので、上記のキャストではRGBQUADの部分を関係ないメモリの内容で埋めてしまっているのではないかと思います。ここを直せばよいのではないかと思います。

投稿 2017/12/07 10:08

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/12/07 17:32

    回答ありがとうございます。CreateDIBitmapの第5引数を変えればよいということでしょうか、、、?もしそうだとすると、具体的に何を入れるとよいのでしょうか?理解不足で申し訳ありません。

    キャンセル

0

KoichiSugiyama 氏の言わんとする所は

#include <math.h>
#define ID_MYTIMER 1

typedef struct{
    HINSTANCE hi0;
    HWND hwin7;
    BYTE *lpBmpData;
    BITMAPINFO bmi;
    char *fname;
    int fsize;
} IMG;

IMG g_img;

LRESULT CALLBACK WndProc_bitmap( HWND hWnd_bitmap, UINT msg, WPARAM wp, LPARAM lp )
{

    PAINTSTRUCT ps;
    HDC hdc, hdc_mem;
    HBITMAP hBmp;
    float x,y,z,r;
    int a, b, ab;
    float lam1,lam2,lam3;

    g_img.bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    g_img.bmi.bmiHeader.biWidth = 659/*674*/;
    g_img.bmi.bmiHeader.biHeight = -494/*532*/;
    g_img.bmi.bmiHeader.biPlanes = 1;
    g_img.bmi.bmiHeader.biBitCount = 32;
    g_img.bmi.bmiHeader.biCompression = BI_RGB;
    g_img.bmi.bmiHeader.biSizeImage = 659/*674*/ * 494/*532*/ * 4;
    g_img.bmi.bmiHeader.biXPelsPerMeter = 3704;
    g_img.bmi.bmiHeader.biYPelsPerMeter = 3704;
    g_img.bmi.bmiHeader.biClrUsed = 0;
    g_img.bmi.bmiHeader.biClrImportant = 0;

    g_img.lpBmpData = (BYTE *)malloc(659/*674*/*494/*532*/*4);

    switch (msg) {
        case WM_CREATE: //ウインドウが生成されたときに1度だけ通過
        //時間割り込みの発生タイミングを設定
        SetTimer(hWnd_bitmap, ID_MYTIMER, 150, NULL);
        break;

        case WM_TIMER:
        if (wp != ID_MYTIMER) return (DefWindowProc(hWnd_bitmap, msg, wp, lp));
        k +=1;
        InvalidateRect(hWnd_bitmap, NULL, FALSE);
        break;

        case WM_PAINT:
        hdc = BeginPaint(hWnd_bitmap, &ps);
        hdc_mem = CreateCompatibleDC( hdc );
        q = 0;
        p = 0;
        for ( a = 0; a < 494/*532*/; a++){
            for( b = 0; b < 659/*674*/; b++){
                ab = a*(659/*674*/*4) + b*4; //始めの項が行数、次の項が左から何ビット目かを表す。(blueの位置を決めている)
                if((b-329.5)*(b-329.5)+(a-494)*(a-494) <= (s[k]/4*1000000*329.5+0.5)*(s[k]/4*1000000*329.5+0.5)){
                    p = p+1.0; //円の内側のピクセル数の合計
                    x = b-329.5;
                    y = 494-a;
                    z = sqrtf(-(x*x)-(y*y)+(s[k]/4*1000000*329.5+0.5)*(s[k]/4*1000000*329.5+0.5));
                    r = sqrtf(x*x + y*y + z*z);
                    lam1 = (x*XSUNm_3[k] + y*YSUNm_3[k] + z*ZSUNm_3[k])/(r*SUN_MOON[k]); //太陽の方向との内積
                    lam2 = (x*XEARTHm_3[k] + y*YEARTHm_3[k] + z*ZEARTHm_3[k])/(r*EARTH_MOON[k]); //地球の方向との内積
                    lam3 = (x*XEQLm_3[k] + y*YEQLm_3[k] + z*ZEQLm_3[k])/(r*EQL_MOON[k]); //EQLの方向との内積
                    // g_img.lpBmpData[ab] = 179*lam3;
                    // g_img.lpBmpData[ab+1] = 179*lam3;
                    // g_img.lpBmpData[ab+2] = 179*lam3;
                    // g_img.lpBmpData[ab+3] = 0;
                    if(lam2>0){
                        g_img.lpBmpData[ab] = 230*lam2;
                        g_img.lpBmpData[ab+1] = 216*lam2;
                        g_img.lpBmpData[ab+2] = 0;
                        g_img.lpBmpData[ab+3] = 0;
                    }
                    if(lam1>0){
                        g_img.lpBmpData[ab] = 0;
                        g_img.lpBmpData[ab+1] = 255*lam1;
                        g_img.lpBmpData[ab+2] = 255*lam1;
                        g_img.lpBmpData[ab+3] = 0;
                    }
                    if(!(lam1>=0 || lam2>=0) ){
                        g_img.lpBmpData[ab] = 179*lam3;
                        g_img.lpBmpData[ab+1] = 179*lam3;
                        g_img.lpBmpData[ab+2] = 179*lam3;
                        g_img.lpBmpData[ab+3] = 0;
                        q = q+1;
                    }
                    if(494 < (s[k]/4*1000000*329.5+0.5)) ok = q*100/325546;
                    if(494 >= (s[k]/4*1000000*329.5+0.5)) ok = q*100/p/*(M_PI* (s[k]/4*1000000*329.5+0.5)*(s[k]/4*1000000*329.5+0.5)/2)*/;
                }
                else{
                    if((b-329.5)*(b-329.5)+(a-494)*(a-494) > (s[k]/4*1000000*329.5+0.5)*(s[k]/4*1000000*329.5+0.5)){
                        g_img.lpBmpData[ab] = 0;
                        g_img.lpBmpData[ab+1] = 0;
                        g_img.lpBmpData[ab+2] = 0;
                        g_img.lpBmpData[ab+3] = 0;
                    }
                }
            }
            hBmp = CreateDIBitmap(hdc, &(g_img.bmi.bmiHeader), CBM_INIT, g_img.lpBmpData,&(g_img.bmi), DIB_RGB_COLORS);
            free(g_img.lpBmpData);
            SelectObject(hdc_mem, hBmp);
            SetStretchBltMode(hdc, COLORONCOLOR);
            StretchBlt(hdc, 0, 0, 659/*674*/, 494/*532*/, hdc_mem, 0, 0, 659/*674*/, 494/*532*/, SRCCOPY);
            DeleteDC( hdc );
            DeleteDC( hdc_mem );
            DeleteObject( hBmp );
            EndPaint(hWnd_bitmap, &ps);
            ReleaseDC( hWnd_bitmap, hdc );
            break;
        }
    }
}

ということだと思われます。

投稿 2017/12/10 01:13

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/12/10 18:44

    回答ありがとうございます。それだとビルド失敗し、「引数 5 を 'BITMAPINFOHEADER *' から 'const BITMAPINFO *' へ変換できません。」とでてきます。なにかアドバイスあればよろしくお願いいたします。

    キャンセル

  • 2017/12/10 18:53

    IMG構造体は書き換えていますか?書き換えていればそんなエラーにならないはず。

    キャンセル

  • 2017/12/10 18:57

    書き換えていないです。見落としていました。もう一度書き直してやってみます。ありがとうございます!

    キャンセル

  • 2017/12/10 19:02

    すいません、bmiHeaderを入れるとtagBITMAPINFOHEDERにありませんとなるのですが、これはどこで定義するのでしょうか?

    キャンセル

  • 2017/12/10 19:04

    あ、BITMAPINFOですね、すいません早とちりで汗やり直します。

    キャンセル

  • 2017/12/10 19:07 編集

    はい・・・?何を言ってるやらさっぱり分からん。
    https://msdn.microsoft.com/ja-jp/library/windows/desktop/dd183375(v=vs.85).aspx
    を見る限り、BITMAPINFO構造体にはbmiHeaderというBITMAPINFOHEDER型の変数がある。
    エラーになる訳がない。というよりエラーメッセージは要約せず原文まま書いてくれ。

    キャンセル

  • 2017/12/10 19:12

    ビルドできましたが実行すると状況は変わりませんでした、、、

    キャンセル

  • 2017/12/10 19:22

    確保しているメモリーのアドレスを表示するようにしてエラーメッセージのアドレスを比較して原因を追求してくださいとしか・・・

    キャンセル

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

ただいまの回答率

91.37%

関連した質問

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

  • C

    2524questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    2409questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • Visual Studio

    1202questions

    Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

  • トップ
  • C++に関する質問
  • ハンドルされない例外、書き込み中にアクセス違反。タイマー関数を使いビットマップ形式で球を描画したいのだが、描画途中で描画されなくなる