2012-03-10 45 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);