2012-03-10 13 views
1

何らかの理由で、渡された構造体の値が、私にアクセスすることなく変更されます。私はこれをVisual Studioでデバッグして見つけました。コードは次のとおりです。C++ - 値が予期せず変更される

bool Screen::blitSurface(SDL_Surface* src, int x, int y, SDL_Rect* rect) { 
    SDL_Rect* offset; 
    offset->x = x; 
    offset->y = y; 

    SDL_BlitSurface(src, rect, screen, offset); 

    return true; 
} 

変更される構造体は 'rect'です。それが渡されると、rect-> xは0、rect-> yは16です。しかし、次のブレークポイント(offset-> x = x;)ではrect-> xは乱数です(たとえば-13108)。 rect-> yと同じです。誰がなぜこのようなことが起こるかについてのアイデアはありますか?私は完全に迷っていて、どこから始めたらいいのかわかりません。

--EDIT--

[OK]を、私はこれにコードを更新し、それはまだ問題を抱えています。

bool Screen::blitSurface(SDL_Surface* src, int x, int y, SDL_Rect* rect) { 
    SDL_Rect offset; 
    offset.x = x; 
    offset.y = y; 

    SDL_BlitSurface(src, rect, screen, &offset); 

    return true; 
} 

しかし、私は考えました。ローカルの構造体を作成してポインタを返すと、関数が完了するとその構造体は削除されますか?たとえば、これは機能しますか?

SDL_Rect* getRect(int x, int y, int width, int height) { 
    SDL_Rect rect; 

    rect.x = x; 
    rect.y = y; 
    rect.w = width; 
    rect.h = height; 

    return ▭ 
} 

これは、私が 'blitSurface'に渡す 'rect'変数を取得する場所です。

+1

あなたは・オフセット 'のための任意のメモリを割り当てられていませんでした。これはどのように機能すると思いますか? – ildjarn

+0

"次のブレークポイント"はどこですか?関数が返った後? 'SDL_BlitSurface()'の呼び出し後? –

+0

変更するのは 'rect'ではなく' * rect'です。スプーンとあなたの区別のようなものです。 –

答えて

2

このコードは間違っている:ここ

SDL_Rect* offset; 
offset->x = x; 
offset->y = y; 

offsetが初期化されていないポインタです。初期化されていないポインタにアクセスすると、プログラムが常にクラッシュするとは限りませんが、常にエラーになります。私はここでポインタを使用しません。あなたが初期化されていないポインタ(または無効1)にアクセスすると

SDL_Rect offset; 
offset.x = x; 
offset.y = y; 
SDL_BlitSurface(src, rect, screen, &offset); 

、あなたは基本的にコンピュータのメモリの任意の部分の上に走り書きするためにコンピュータを語っています。最善のシナリオでは、プログラムがクラッシュします。最悪の場合のシナリオでは、クラッシュすることはありません。

このコードも間違っている:

SDL_Rect rect; 
// ... 
return ▭ 

rectへのポインタが、すぐに関数が終了するとして無効です。ここでもポインタは使用しません。

SDL_Rect getRect(int x, int y, int width, int height) 
{ 
    SDL_Rect rect; 
    rect.x = x; 
    rect.y = y; 
    rect.w = width; 
    rect.h = height; 
    return rect; 
} 

SDL_Rect構造が十分に小さいとあなたが関数からそれを返すこと自由に感じなければならないことは十分に簡単です。あなたは、ポインタを取るSDL関数に結果を渡す必要がある場合は、それをこのようにします:

SDL_Rect r = getRect(...); 

SDL_Some_Function(..., &r, ...); 

ポインタはCやC++に危険です:それはあなたがそれらを使用するべきではないと言うことはありません。しかし、どの条件がポインタを有効または無効にするかを正確に知らなければ、プログラムは正しくありません。コンパイラはこれを理解するのを手助けしませんが、Clangのような静的解析ツールが役に立ちます。

CやC++とは異なり、Python、C#、Java、Haskell、Lisp、Perl、Rubyなどの他のほとんどの言語は、実際に作業しない限り、無効なポインタを作成できません。

+0

ポインタが(SDL_Rect * offset = 5; 'のように)初期化されていても、それは役に立たないでしょう。むしろ、ポインタは有効な値*を持つ必要があります。 –

+0

@KerrekSB:はい、そうです。私は起こりうるすべての間違ったことを明示的に列挙しなかった。 –

2

2ワード:未定義の動作

SDL_Rect* offset; 
    offset->x = x; 
    offset->y = y; 

初期化されていない変数にアクセスしています。

どちらかoffsetを割り当てる:

SDL_Rect* offset = new SDL_Rect; 

または自動メモリでそれを持っている:

SDL_Rect offset; 
    offset.x = x; 
    offset.y = y; 

    SDL_BlitSurface(src, rect, screen, &offset); 
関連する問題