C ++ - 值意外地改变

时间:2012-03-10 21:34:15

标签: c++

由于某种原因,传递的struct的值在我没有访问它们的情况下发生了变化。我通过Visual Studio调试发现了这一点。这是代码:

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'。

2 个答案:

答案 0 :(得分: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)不允许您创建无效指针,除非您真正使用它。

答案 1 :(得分: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 );