V
V
Vitaly Stolyarov2017-04-10 18:36:03
C++ / C#
Vitaly Stolyarov, 2017-04-10 18:36:03

How to fix memory leak in recursion?

#include <inttypes.h>
#include <stdio.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include <vector>
#include <iostream>
#include <memory>
#include <time.h>

struct ChunkId {
  int low;
  int high;
};
using FloatArray = float*;// std::unique_ptr<float[]>;
class OctaTerrain {

  
private:
  float RADIUS;
  int MAX_Z;
  float DETAIL_LEVEL;
  std::vector<int64_t> existChunksId;
  std::vector<float*> existChunksVertices;
  FloatArray cameraPosition;

  float theta = M_PI / 2;
  float phi = M_PI / 2;

public:
  OctaTerrain(float radius, int max_z, float detail) {
    RADIUS = radius;
    MAX_Z = max_z;
    DETAIL_LEVEL = detail;
    cameraPosition = FloatArray(new float[3]{ RADIUS,0,0 });
  }

  FloatArray toPoint(float lat, float lon) {
    return FloatArray(new float[3]{
      RADIUS * (float)cos(lat) * (float)sin(lon),
      RADIUS * (float)sin(lat),
      RADIUS * (float)cos(lat) * (float)cos(lon)
    });
  }


  float distance(FloatArray &a, FloatArray &b) {
    return sqrt(pow(a[0] - b[0], 2) + pow(a[1] - b[1], 2) + pow(a[2] - b[2], 2));
  }

  bool needDivide(FloatArray &v1, FloatArray &coords, int z) {
    FloatArray v2 = toPoint(coords[0], coords[1]);

    if (distance(v1, v2) < pow(DETAIL_LEVEL / z, 2)) {
      delete[] v2;
      return true;
    }

    delete[] v2;
    return false;
  }


  FloatArray getChunkCenter(FloatArray &p1, FloatArray &p2, FloatArray &p3) {
    return FloatArray(new float[2]{ (p1[0] + p2[0] + p3[0]) / 3,(p1[1] + p2[1] + p3[1]) / 3 });
  }
  /*
  int64_t increaseIdLevel(int64_t id) {
    return id + ((int64_t)0x1 << 7 * 8);
  }

  int getIdLevel(int64_t id) {
    return id >> 7 * 8;
  }

  int64_t setIdSide(int side) {
    return (int64_t)side << 6 * 8;
  }

  int getIdSide(int64_t id) {
    return (id >> 6 * 8) & 0xffff;
  }

  int64_t setIdIndex(int64_t id, int index) {
    return id | ((int64_t)index << getIdLevel(id) * 2);
  }
  */
  int k = 0;
  void addChunk(FloatArray &p1, FloatArray &p2, FloatArray &p3, int z){//int64_t id) {
    
    //int z = getIdLevel(id);
    FloatArray center = getChunkCenter(p1, p2, p3);
    

    if (z < MAX_Z && needDivide(cameraPosition, center, z)) {

      FloatArray p12(new float[2]{ (p1[0] + p2[0]) / 2,(p1[1] + p2[1]) / 2 });
      FloatArray p23(new float[2]{ (p2[0] + p3[0]) / 2,(p2[1] + p3[1]) / 2 });
      FloatArray p31(new float[2]{ (p1[0] + p2[0]) / 2,p1[0] == M_PI ? p3[1] : (p3[1] + p1[1]) / 2 });
      // Align the longitude of the right side along the edge for the upper triangles

      //id = increaseIdLevel(id);
      z++;
      addChunk(p1, p12, p31, z);// setIdIndex(id, 0));
      addChunk(p12, p23, p31, z);// setIdIndex(id, 1));
      addChunk(p12, p2, p23, z);// setIdIndex(id, 2));
      addChunk(p31, p23, p3, z);// setIdIndex(id, 3));

      //delete[] center,p12,p23,p31;
      return;
    }
    //delete[] center;
    k++;
  //	existChunksId.push_back(id);
  }

  void addSide(int id) {
    float latScalar = (id>3 ? -1 : 1);
    float lonScalar = id % 4;

    FloatArray p1(new float[2]{ latScalar*theta, lonScalar*phi });
    FloatArray p2(new float[2]{ 0.0,lonScalar*phi });
    FloatArray p3(new float[2]{ 0.0,(lonScalar + 1)*phi });
    addChunk(p1, p2, p3, 0);// setIdSide(id));
    //delete[] p1, p2, p3;
  }

  void generate(float x, float y, float z) {
    cameraPosition = FloatArray(new float[3]{ x,y,z });
    existChunksId.clear();

    
    addSide(1);
  //	addSide(1);
    // for(int i = 0; i<8;i++)
    //  	addSide(i);

    printf("%d", k);// existChunksId.size());
  }

  std::vector<ChunkId> getIds() {

    std::vector<ChunkId>  v;
    // std::sort(existChunksId.begin(), existChunksId.end());

    for (const int64_t& i : existChunksId) {
      ChunkId chunk;
      chunk.high = i >> 32;
      chunk.low = i & 0xffffffff;
      v.push_back(chunk);
    }

    return v;
  }
};

int main() {
auto terrain = new OctaTerrain(1,20,1);

time_t start, end;
time(&start);

terrain->generate(1.002,0,0);

time(&end);
double dif = difftime(end, start);
printf("\n%lf\n", dif);
std::cin.get();
return 0;
}

All new have corresponding delete[], but only half of the memory is cleared with them (with the existing parameters in generate: without delete[] eats up more than 400 MB, with delete[] - 210.
I use VS C++ 2015

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Maxim Moseychuk, 2017-04-10
@Ni55aN

1) Use smart pointers.
2) If the recursion is deep, then this memory can be eaten by the stack, not the heap.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question