问题
I want to know how to properly delete the memory of std::vector & std:: map allocated in c++ code.
I am sharing my code here
# include <vector>
# include <stdio.h>
# include <stdlib.h> //realloc
# include <math.h>
# include <map>
# include <unordered_map>
#include <emscripten/bind.h>
using namespace emscripten;
struct Edge{
// Coordinates of two vertices
float c[6];
float normal[3];
int i1,
i2;
Edge() {};
Edge(const float * v1, const float * v2, const float * _normal, int _i1, int _i2) {
i1 = _i1;
i2 = _i2;
memcpy( & normal[0], _normal, 3 * sizeof(float));
// Compare coordinates lexicographically to select some fixed edge direction
if (std::lexicographical_compare( & v1[0], & v1[3], & v2[0], & v2[3])) {
memcpy( & c[0], v1, 3 * sizeof(float));
memcpy( & c[3], v2, 3 * sizeof(float));
} else {
memcpy( & c[0], v2, 3 * sizeof(float));
memcpy( & c[3], v1, 3 * sizeof(float));
}
}
// Comparison operator for storing edges in std::map
bool operator < (const Edge & e)const{
return std::lexicographical_compare( & c[0], & c[6], & e.c[0], & e.c[6]);
}
bool operator ==(const Edge & edge)const{
// return std::lexicographical_compare( & c[0], & c[6], & e.c[0], & e.c[6]);
if(c[0] == edge.c[0] && c[1] == edge.c[1] && c[2] == edge.c[2] &&
c[3] == edge.c[3] && c[4] == edge.c[4] && c[5] == edge.c[5]
)
return true;
else
return false;
}
};
std::vector < float > crossProduct(std::vector < float > vector1, std::vector < float > vector2) {
std::vector < float > value;
value.resize(3);
value[0] = ((vector1[1] * vector2[2]) - (vector1[2] * vector2[1]));
value[1] = ((vector1[2] * vector2[0]) - (vector1[0] * vector2[2]));
value[2] = ((vector1[0] * vector2[1]) - (vector1[1] * vector2[0]));
return value;
}
std::vector < float > subVector(float * vector1, float * vector2) {
std::vector < float > value;
value.resize(3);
value[0] = ((vector1[0]) - (vector2[0]));
value[1] = ((vector1[1]) - (vector2[1]));
value[2] = ((vector1[2]) - (vector2[2]));
return value;
}
std::vector < float > Normalize(std::vector < float > vector) {
float length = sqrt(pow((vector[0]), 2) + pow((vector[1]), 2) + pow((vector[2]), 2));
if (length > 0) {
std::vector < float > value;
value.resize(3);
value[0] = vector[0] / length;
value[1]= vector[1] / length;
value[2] = vector[2] / length;
return value;
}
return vector;
}
std::vector<unsigned int> GetFeatureEdges(float fCreaseAngle, uintptr_t input, int nTriangles, bool bBoundaryEdgesOnly){
std::vector < Edge > edges;
const float* coords = reinterpret_cast<float*>(input);
int nEdges = 3 * nTriangles;
edges.resize(nEdges);
# pragma omp parallel for
for (int i = 0; i < nTriangles; i++) {
int t = 3 * i;
int y = 3 * 3 * i;
float p[3][3];
memcpy( & p[0], & coords[y], sizeof(float) * 9);
std::vector < float > normal = crossProduct(subVector(p[1], p[0]), subVector(p[2], p[0]));
normal = Normalize(normal);
for (int j = 0; j < 3; j++) {
int k = (j + 1) % 3;
edges[i * 3 + j] = Edge( & p[j][0], & p[k][0], & normal[0], t + j, t + k);
}
}
float threshold = cos(fCreaseAngle * M_PI / 180);
std::map < Edge, unsigned char > edge_info;
for (int i = 0; i < nEdges; i++) {
std::map < Edge,
unsigned char > ::iterator it = edge_info.find(edges[i]);
if (it == edge_info.end())
edge_info[edges[i]] = 1; // Add edge and mark it as unpaired
else if (it->second == 1) {
if (bBoundaryEdgesOnly) {
edge_info.erase(it);
} else {
float dot = edges[i].normal[0] * it->first.normal[0] + edges[i].normal[1] * it->first.normal[1] + edges[i].normal[2] * it->first.normal[2];
if (dot > 1.0f)
dot = 1.0f;
else if (dot < -1.0f)
dot = -1.0f;
if (dot > threshold) {
it->second = 2; // Mark edge as as unpaired, because faces are within crease angle
edge_info.erase(it);
} else
it->second = 0; // Mark edge as forced feature edge (this is for case when edge is shared by 3+ faces)
}
}
}
std::vector<unsigned int> res;
res.resize(edge_info.size() * 2);
size_t count=0;
for (std::map<Edge, unsigned char>::const_iterator it = edge_info.begin(); it != edge_info.end(); it++)
{
res[count++]=it->first.i1;
res[count++]=it->first.i2;
}
edges.clear();
edge_info.clear();
return res;
}
EMSCRIPTEN_BINDINGS(VCT_wrappers) {
register_vector<unsigned int>("VectorUInt");
function("GetFeatureEdges", &GetFeatureEdges, allow_raw_pointers());
}
emcc compilation is
emcc --bind -o featureEdge.js featureEdge.cpp -O3 --memory-init-file 0 -s ALLOW_MEMORY_GROWTH=1 -v
and my js function code is
function _arrayToHeap(typedArray) {
var numBytes = typedArray.length * typedArray.BYTES_PER_ELEMENT;
var ptr = Module._malloc(numBytes);
var heapBytes = new Uint8Array(Module.HEAPU8.buffer, ptr, numBytes);
heapBytes.set(new Uint8Array(typedArray.buffer));
return heapBytes;
}
function _freeArray(heapBytes) {
Module._free(heapBytes.byteOffset);
}
function GetFeatureEdges_asm(nodeName, fCreaseAngle, vertices, nTriangles, bBoundaryEdgesOnly) {
//var vertices = new Float32Array([0, 0, 0, 10, 0, 0, 5, 10, 0,
// 10, 0, 0, 10, 10, 0, 5, 10, 0,
// 0, 0, 0, 5, 10, 0, 0, 10, 0]);
//nTriangles = vertices.length / 3 / 3;
// console.log(nTriangles);
//var startTime = Date.now();
var dataHeap1 = _arrayToHeap(vertices);
var obj = Module.GetFeatureEdges(35.0, dataHeap1.byteOffset, nTriangles, 0);
var count = obj.size();
var indexData = new Uint32Array(count);
for (var i = 0; i < count; i++)
indexData[i] = obj.get(i);
obj.resize(0, 0);
obj.delete();
_freeArray(dataHeap1);
//var diffTime = Date.now() - startTime;
//time = time + diffTime
return indexData;
}
Here "vertices" is very big array of float values.
If i use this
struct Edge *edges = new struct Edge[nEdges];
delete[] edges;
edges = NULL;
instead of
std::vector < Edge > edges;
edges.resize(nEdges);
there is not memory leak in chrome browser and my emscripten version is 1.37.21.
can any one help me in this?
来源:https://stackoverflow.com/questions/48497630/emscripten-memory-leak-with-stdvector-stdmap-in-c-code