Ni55aN
@Ni55aN

Как устранить утечку памяти в рекурсии?

#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;
}


Ко всем new есть соответствующие delete[], но с ними очищается только половина памяти (с имеющимися параметрами в generate: без delete[] съедает больше 400 МБ, с delete[] - 210.
Использую VS C++ 2015
  • Вопрос задан
  • 403 просмотра
Решения вопроса 1
1) Использовать умные указатели.
2) Если рекурсия глубокая, то эту память может отжирать стек, а не куча.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы