为什么用指针调用GetWindowRect会导致异常,但地址却不会

时间:2013-02-28 18:28:16

标签: c++ c++builder

我在dll中有一个实用程序功能,可以将我的表单放在主机应用程序屏幕上。我正在使用RAD Studio XE2。我必须手动执行此操作,因为主机应用程序是非VCL并且TForm的表单放置参数无法正常工作。以下代码有效。这两个函数都声明为static,我之前已将Application handle属性设置为host app。

   void MyClass::GetAppCenter(POINT * pos) {
      RECT Rect;
      GetWindowRect(Application->Handle, &Rect);
      pos->x = (Rect.left + Rect.right) / 2;
      pos->y = (Rect.top + Rect.bottom) / 2;
   }

   void MyClass::PlaceForm(TForm * f) {
      POINT pos;
      GetAppCenter(&pos);
      for (int i = 0; i < Screen->MonitorCount; i++) {
         TRect r = Screen->Monitors[i]->WorkareaRect;
         if (r.Contains(pos)) {
            f->Left = (r.Left + r.Right) / 2 - f->Width / 2;
            f->Top = (r.Top + r.Bottom) / 2 - f->Height / 2;
            return;
         }
      }
   }

我的初始GetAppCenter代码使用了Rect *而返回了正确的值,但在设置f-&gt; Left时抛出了Access Violation异常。任何人都可以解释原因吗?

   // original version
   void OasisUtils::GetOasisCenter(POINT * pos) {
      RECT *Rect;
      GetWindowRect(Application->Handle, Rect);
      pos->x = (Rect->left + Rect->right) / 2;
      pos->y = (Rect->top + Rect->bottom) / 2;
      delete Rect; // tried with and without this
   }

2 个答案:

答案 0 :(得分:4)

  RECT *Rect;
  GetWindowRect(Application->Handle, Rect);
  //Rect->left 

这是不正确的。 GetWindowRect需要一个有效的RECT*参数,以便填充此指针指向的内存。你正在传递一个未初始化的指针,期望一些魔法会使它有效。相反,您将获得访问冲突。你需要:

  RECT Rect;
  GetWindowRect(Application->Handle, &Rect); // <<--- Note &
  //Rect.left 

答案 1 :(得分:3)

GetWindowRect期望调用者拥有矩形结构。

在原始版本中,*Rect未指向任何有效内存。因此,当您尝试使用它时,您将访问一些您不拥有的随机内存块。操作系统否认了这一点。我很惊讶调用GetWindowRect不会导致崩溃。

另一方面,您的更新版本声明RECT Rect,它在堆栈上分配内存。调用函数时会自动分配该内存,并在函数完成时清除该内存。

为了澄清,这个问题与指针和引用之间的差异无关。问题完全是由于内存分配/所有权。