2012-03-10 44 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相同。有人有一個想法,爲什麼發生這種情況?我完全迷失了,不知道從哪裏開始。

- 編輯 -

好吧,我更新的代碼這一點,但它仍然有問題。

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 ▭ 
} 

這是我得到的'rect'變量,我傳遞給'blitSurface'。

+1

您還沒有分配給'offset'任何記憶;你如何期待這個工作? – ildjarn 2012-03-10 21:36:03

+0

「下一個斷點」在哪裏?函數返回後?在調用'SDL_BlitSurface()'之後? – 2012-03-10 21:37:07

+0

這不是'rect',而是'rect'。這有點像勺子和你之間的區別。 – 2012-03-10 21:38:00

回答

2

這段代碼是錯誤的:

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

這裏,offset是未初始化的指針。訪問未初始化的指針始終是一個錯誤,即使它並不總是會導致程序崩潰。我不會在這裏使用指針。

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;'),它也無濟於事。相反,指針需要*有一個有效的值*。 – 2012-03-10 21:39:24

+0

@KerrekSB:是的,你說得對。我沒有明確列舉可能發生的所有可能的錯誤事情。 – 2012-03-10 21:41:24

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);