delete []调用析构函数时出现内存错误

时间:2015-03-04 20:10:07

标签: c++

我正在尝试制作一个可以计算闭合多边形链面积的程序。该程序似乎输出正确的结果,直到...它达到返回0;在主要功能。

调试器显示退出main函数时,程序在polygon.h中的第17行调用Vertex的析构函数,那就是当一切都变成混乱时!析构函数尝试释放Vertex *顶点指向的动态分配空间。但它没有这样做,而是给出了一个很长的错误信息,我已经粘贴在下面。

在试图解决这个问题一段时间后,我别无选择,只能寻求帮助。有人可以告诉我的程序有什么问题吗?

提前致谢

  

错误消息

==9715== Conditional jump or move depends on uninitialised value(s)
==9715==    at 0x400C8A: Polygon::add(Vertex const&) (Polygon.cpp:25)
==9715==    by 0x40147C: main (main.cpp:16)
==9715== 
==9715== Invalid write of size 8
==9715==    at 0x401198: Vertex::setX(int) (Vertex.h:12)
==9715==    by 0x400E07: Polygon::add(Vertex const&) (Polygon.cpp:42)
==9715==    by 0x40147C: main (main.cpp:16)
==9715==  Address 0x5959080 is 0 bytes after a block of size 64 alloc'd
==9715==    at 0x4C28147: operator new[](unsigned long) (vg_replace_malloc.c:348)
==9715==    by 0x400B5E: Polygon::Polygon(Vertex*, int) (Polygon.cpp:13)
==9715==    by 0x401281: main (main.cpp:8)
==9715== 
==9715== Invalid write of size 8
==9715==    at 0x4011B2: Vertex::setY(int) (Vertex.h:13)
==9715==    by 0x400E2B: Polygon::add(Vertex const&) (Polygon.cpp:43)
==9715==    by 0x40147C: main (main.cpp:16)
==9715==  Address 0x5959088 is 8 bytes after a block of size 64 alloc'd
==9715==    at 0x4C28147: operator new[](unsigned long) (vg_replace_malloc.c:348)
==9715==    by 0x400B5E: Polygon::Polygon(Vertex*, int) (Polygon.cpp:13)
==9715==    by 0x401281: main (main.cpp:8)
==9715== 
num:  5
==9715== Invalid read of size 8
==9715==    at 0x401174: Vertex::getY() const (Vertex.h:11)
==9715==    by 0x400ED1: Polygon::area() const (Polygon.cpp:58)
==9715==    by 0x4014C2: main (main.cpp:18)
==9715==  Address 0x5959088 is 8 bytes after a block of size 64 alloc'd
==9715==    at 0x4C28147: operator new[](unsigned long) (vg_replace_malloc.c:348)
==9715==    by 0x400B5E: Polygon::Polygon(Vertex*, int) (Polygon.cpp:13)
==9715==    by 0x401281: main (main.cpp:8)
==9715== 
==9715== Invalid read of size 8
==9715==    at 0x40115A: Vertex::getX() const (Vertex.h:10)
==9715==    by 0x400F08: Polygon::area() const (Polygon.cpp:59)
==9715==    by 0x4014C2: main (main.cpp:18)
==9715==  Address 0x5959080 is 0 bytes after a block of size 64 alloc'd
==9715==    at 0x4C28147: operator new[](unsigned long) (vg_replace_malloc.c:348)
==9715==    by 0x400B5E: Polygon::Polygon(Vertex*, int) (Polygon.cpp:13)
==9715==    by 0x401281: main (main.cpp:8)
==9715== 
==9715== Invalid read of size 8
==9715==    at 0x40115A: Vertex::getX() const (Vertex.h:10)
==9715==    by 0x400F90: Polygon::area() const (Polygon.cpp:63)
==9715==    by 0x4014C2: main (main.cpp:18)
==9715==  Address 0x5959080 is 0 bytes after a block of size 64 alloc'd
==9715==    at 0x4C28147: operator new[](unsigned long) (vg_replace_malloc.c:348)
==9715==    by 0x400B5E: Polygon::Polygon(Vertex*, int) (Polygon.cpp:13)
==9715==    by 0x401281: main (main.cpp:8)
==9715== 
==9715== Invalid read of size 8
==9715==    at 0x401174: Vertex::getY() const (Vertex.h:11)
==9715==    by 0x400FED: Polygon::area() const (Polygon.cpp:64)
==9715==    by 0x4014C2: main (main.cpp:18)
==9715==  Address 0x5959088 is 8 bytes after a block of size 64 alloc'd
==9715==    at 0x4C28147: operator new[](unsigned long) (vg_replace_malloc.c:348)
==9715==    by 0x400B5E: Polygon::Polygon(Vertex*, int) (Polygon.cpp:13)
==9715==    by 0x401281: main (main.cpp:8)
==9715== 
area:  39
minx: -1
trianglearea: 4.5
==9715== 
==9715== HEAP SUMMARY:
==9715==     in use at exit: 0 bytes in 0 blocks
==9715==   total heap usage: 4 allocs, 4 frees, 176 bytes allocated
==9715== 
==9715== All heap blocks were freed -- no leaks are possible
==9715== 
==9715== For counts of detected and suppressed errors, rerun with: -v
==9715== Use --track-origins=yes to see where uninitialised values come from
==9715== ERROR SUMMARY: 7 errors from 7 contexts (suppressed: 4 from 4)
  

/ * main.cpp * /

#include <iostream>
#include "Polygon.h"
using namespace std;

int main() {
  Vertex varr[] = { Vertex(0,0), Vertex(6,0),
                    Vertex(6,6), Vertex(0,6) };
  Polygon pol( varr, 4 );
  cout << "num:  " <<  pol.numVertices() << endl;
  cout << "area:  " <<  pol.area() << endl;
  cout << "minx: " <<  pol.minX() << endl;
  cout << "maxx: " <<  pol.maxX() << endl;
  cout << "miny: " <<  pol.minY() << endl;
  cout << "maxy: " <<  pol.maxY() << endl;

  pol.add( Vertex(-1,3) );
  cout << "num:  " <<  pol.numVertices() << endl;
  cout << "area:  " <<  pol.area() << endl;
  cout << "minx: " <<  pol.minX() << endl;

  Polygon pol1;
  pol1.add( Vertex(0,0) );
  pol1.add( Vertex(3,3) );
  pol1.add( Vertex(3,0) );

  cout << "trianglearea: " << pol1.area() << endl;

  return 0;
}
  

/ * Vertex.cpp * /

#include "Vertex.h"

Vertex::Vertex(int newx, int newy) {
  x = newx;
  y = newy;
}
  

/ * Vertex.h * /

#ifndef VERTEX_H
#define VERTEX_H

class Vertex {
 private:
  double x, y;
 public:
  Vertex() {x = 0; y = 0;};
  Vertex(int newx, int newy);
  double getX() const { return x; }
  double getY() const { return y; }
  void setX(const int newx) { x = newx; }
    void setY(const int newy) { y = newy; }
};
  

/ * Polygon.cpp * /

#include "Polygon.h"
#include <cmath> // For abs

// Constructor sets array of v to be the vertices of polygon
Polygon::Polygon( Vertex * const v, const int newSize ) : size(newSize) {

  // Set first element to min and max
  minx = maxx = (v[0]).getX();
  miny = maxy = (v[0]).getY();

  // Add vertices and set min/max
  int x, y;
  vertices = new Vertex[size];
  for (int i = 0; i < size; i++) {
    x = v[i].getX();
    y = v[i].getY();
    (vertices[i]).setX(x);
    (vertices[i]).setY(y);
    if (i > 0)
      setMinMax(x, y);
  }
}

/* Add a single vertex */
void Polygon::add( const Vertex& v ) {
  if (size == maxSize) {
    maxSize *= 2;
    Vertex * tempPointer = new Vertex[maxSize];

    // Copy elements of previous vertice array to new one
    for (int i = 0; i < size; i++) {
      (tempPointer[i]).setX((vertices[i]).getX());
      (tempPointer[i]).setY((vertices[i]).getY());
    }

    delete [] vertices;
    vertices = tempPointer;
    tempPointer = 0;
  }

  // Add single vertex to the end of vertices array
  int x = v.getX();
  int y = v.getY();
  (vertices[size]).setX(x);
  (vertices[size]).setY(y);
  setMinMax(x, y);
  size++;
}

/* Calculate area using formula on http://mathworld.wolfram.com/PolygonArea.html */
double Polygon::area() const {
  double area = 0, term1, term2;

  // Area must be 0 if nbr of vertices is < 3
  if (size < 3) {
    return area;
  }

   // Sum initial terms in formula
  int i;
  for (i = 0; i < size-1; i++) {
    term1 = ( vertices[i].getX() * vertices[i+1].getY() ) / 2;
    term2 = ( vertices[i+1].getX() * vertices[i].getY() ) / 2;
    area += (term1 - term2);
  }

  // Sum last term in formula
  term1 = (vertices[i].getX() * vertices[0].getY()) / 2;
  term2 = (vertices[0].getX() * vertices[i].getY()) / 2;
  area += (term1 - term2);
  return fabs(area);
}

void Polygon::setMinMax(const int x, const int y) {
  if (size == 0) {
    minx = maxx = x;
    miny = maxy = y;
  }
  else {
    if (x < minx) { minx = x; }
    if (x > maxx) { maxx = x; }
    if (y < miny) { miny = y; }
    if (y > maxy) { maxy = y; }
  }
}

    #endif /* VERTEX_H */
  

/ * Polygon.h * /

#ifndef POLYGON_H
#define POLYGON_H

#include "Vertex.h"

class Polygon {
 private:
  int size, maxSize;
  Vertex * vertices;
  double minx, miny, maxx, maxy;
  void setMinMax(const int x, const int y);
 public:
 Polygon() : size(0), maxSize(1), vertices(new Vertex[1]) {}
  Polygon( Vertex * const v, const int newSize );
  ~Polygon() { delete [] vertices; }
  void add( const Vertex& v );
  double area() const;
  double minX() const { return minx; }
  double minY() const { return miny; }
  double maxX() const { return maxx; }
  double maxY() const { return maxy; }
  int numVertices() const { return size; }
};

#endif /* POLYGON_H */

1 个答案:

答案 0 :(得分:5)

错误源于在构建带有数组的maxSize类期间未初始化Polygon

Polygon::Polygon( Vertex * const v, const int newSize ) : 
                  size(newSize), maxSize(newSize) 

您应该解决代码中的其他问题。

  1. 当您致电Polygon::add时,您会过早地将maxSize乘以2,但您尚未拨打new[]来分配内存。如果new[]引发异常,您就搞乱了maxSize变量。为了解决这个问题,只需在成功分配内存后更改成员变量(并且在您清除了成功调用任何throwable函数的障碍之后)。

  2. 您应该提供赋值运算符和复制构造函数。如果要使Polygon对象具有正确的复制语义,则应实现这些功能。阅读Rule of 3(以及Rule of 5Rule of 0)。