star-cad

Geometric operators for computer-aided design
git clone git://git.meso-star.fr/star-cad.git
Log | Files | Refs | README | LICENSE

commit a2dd7abd68c66b2973bc8e79686507149f521fe2
parent b1beaf668b5c6ce6dfe9cec4f30645f318281d7a
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Wed, 28 Dec 2022 18:55:18 +0100

Upgrade memory management

Only return objects allocated using provided allocator and fix some leaks

Diffstat:
Msrc/scad.c | 56+++++++++++++++++++++++++++++++-------------------------
Msrc/scad.h | 11++++++++++-
Msrc/scad_geometry.c | 513++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
3 files changed, 356 insertions(+), 224 deletions(-)

diff --git a/src/scad.c b/src/scad.c @@ -282,6 +282,8 @@ scad_stl_export int* data; size_t sz; int str_initialized = 0; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; res_T res = RES_OK; if(!geometry) { @@ -291,7 +293,7 @@ scad_stl_export ERR(check_device(FUNC_NAME)); - if(get_device()->need_synchro) { + if(dev->need_synchro) { ERR(scad_synchronize()); } @@ -299,7 +301,8 @@ scad_stl_export data = geometry->gmsh_dimTags; ASSERT(sz > 0 && sz % 2 == 0); - str_init(get_device()->allocator, &filename); + allocator = dev->allocator; + str_init(allocator, &filename); str_initialized = 1; if(prefix) { ERR(str_set(&filename, prefix)); @@ -339,14 +342,13 @@ scad_stl_export } } - /* Allocate room for arrays - * TODO: use allocator */ - nodeTags = calloc(faces_dimTags_n/2, sizeof(*nodeTags)); - nodeTags_n = calloc(faces_dimTags_n/2, sizeof(*nodeTags_n)); - coord = calloc(faces_dimTags_n/2, sizeof(*coord)); - coord_n = calloc(faces_dimTags_n/2, sizeof(*coord_n)); - pCoord = calloc(faces_dimTags_n/2, sizeof(*pCoord)); - pCoord_n = calloc(faces_dimTags_n/2, sizeof(*pCoord_n)); + /* Allocate room for arrays */ + nodeTags = MEM_CALLOC(allocator, faces_dimTags_n/2, sizeof(*nodeTags)); + nodeTags_n = MEM_CALLOC(allocator, faces_dimTags_n/2, sizeof(*nodeTags_n)); + coord = MEM_CALLOC(allocator, faces_dimTags_n/2, sizeof(*coord)); + coord_n = MEM_CALLOC(allocator, faces_dimTags_n/2, sizeof(*coord_n)); + pCoord = MEM_CALLOC(allocator, faces_dimTags_n/2, sizeof(*pCoord)); + pCoord_n = MEM_CALLOC(allocator, faces_dimTags_n/2, sizeof(*pCoord_n)); if(!nodeTags || !nodeTags_n || !coord || !coord_n || !pCoord || !pCoord_n) { res = RES_MEM_ERR; goto error; @@ -368,27 +370,33 @@ scad_stl_export ERR(write_stl(str_cget(&filename), (unsigned)tcount, coord, coord_n, binary)); exit: + if(!allocator) { + /* Early error, nothing was allocated */ + return res; + } if(str_initialized) str_release(&filename); - free(dimTags_to_free); + gmshFree(dimTags_to_free); if(nodeTags) { - for(i = 0; i < faces_dimTags_n/2; i++) free(nodeTags[i]); - free(nodeTags); + for(i = 0; i < faces_dimTags_n/2; i++) gmshFree(nodeTags[i]); + MEM_RM(allocator, nodeTags); } - free(nodeTags_n); + MEM_RM(allocator, nodeTags_n); if(coord) { - for(i = 0; i < faces_dimTags_n/2; i++) free(coord[i]); - free(coord); + for(i = 0; i < faces_dimTags_n/2; i++) gmshFree(coord[i]); + MEM_RM(allocator, coord); } - free(coord_n); + MEM_RM(allocator, coord_n); if(pCoord) { - for(i = 0; i < faces_dimTags_n/2; i++) free(pCoord[i]); - free(pCoord); + for(i = 0; i < faces_dimTags_n/2; i++) gmshFree(pCoord[i]); + MEM_RM(allocator, pCoord); } - free(pCoord_n); + MEM_RM(allocator, pCoord_n); return res; error: - log_error(get_device(), "%s: could not export to STL -- %s\n", - FUNC_NAME, res_to_cstr(res)); + if(dev) { + log_error(dev, "%s: could not export to STL -- %s\n", + FUNC_NAME, res_to_cstr(res)); + } goto exit; } @@ -490,7 +498,7 @@ exit: str_release(&filename_root); str_release(&filename); } - free(tagout); + gmshFree(tagout); return res; error: goto exit; @@ -522,7 +530,6 @@ res_T scad_scene_partition (void) { - int* dimTags = NULL; int ierr = 0; res_T res = RES_OK; @@ -538,7 +545,6 @@ scad_scene_partition ERR(gmsh_err_to_res_T(ierr)); exit: - free(dimTags); return res; error: goto exit; diff --git a/src/scad.h b/src/scad.h @@ -39,6 +39,7 @@ /* Forward declarations */ struct mem_allocator; struct logger; +struct str; /* Forward declaration of scad opaque data types */ struct scad_geometry; /* Wrapping of dimTags gmsh description */ @@ -159,6 +160,9 @@ scad_geometry_get_count (const struct scad_geometry* geom, size_t* count); +/* Get a pointer to `geom's name. + * Note that this reference is only valid during the lifetime of `geom' (don't + * use name after deleting `geom') */ SCAD_API res_T scad_geometry_get_name (const struct scad_geometry* geom, @@ -171,6 +175,9 @@ scad_geometry_get_mass (struct scad_geometry* geom, double* mass); +/* Get the center of mass of the various components of the geometry. + * Note that `center' is allocated using the allocator provided when + * initializing star-cad and should be freed accordingly. */ SCAD_API res_T scad_geometry_get_centerofmass (struct scad_geometry* geom, @@ -363,7 +370,9 @@ scad_geometry_explode size_t* out_geometry_n); /* Import a step model (`filename'). The imported geometries are recorded in - * `out_geometry' handler. */ + * `out_geometry'. + * Note that `out_geometry' is allocated using the allocator provided when + * initializing star-cad and should be freed accordingly. */ SCAD_API res_T scad_step_import (const char* filename, /* name of step file */ diff --git a/src/scad_geometry.c b/src/scad_geometry.c @@ -56,6 +56,7 @@ geom_set_name const char* name) { struct scad_device* dev = get_device(); + struct mem_allocator* allocator = dev->allocator; struct str str_name; int name_initialized = 0; int same_name; @@ -69,7 +70,7 @@ geom_set_name log_error(get_device(), "Geometry name \"\" is invalid.\n"); goto error; } - str_init(dev->allocator, &str_name); + str_init(allocator, &str_name); name_initialized = 1; ERR(str_set(&str_name, name)); if(htable_names_find(&dev->geometry_names, &str_name)) { @@ -111,17 +112,18 @@ scad_geometry_create res_T res = RES_OK; struct scad_geometry* geom = NULL; struct scad_device* dev = get_device(); + struct mem_allocator* allocator = dev->allocator; char one = 1; ASSERT(out_geometry); - geom = (struct scad_geometry*)MEM_CALLOC(dev->allocator, 1, sizeof(*geom)); + geom = (struct scad_geometry*)MEM_CALLOC(allocator, 1, sizeof(*geom)); if(!geom) { res = RES_MEM_ERR; goto error; } - str_init(dev->allocator, &geom->name); + str_init(allocator, &geom->name); ERR(htable_geometries_set(&dev->allgeom, &geom, &one)); ERR(geom_set_name(geom, name)); dev->need_synchro = 1; @@ -147,14 +149,13 @@ gather_tags res_T res = RES_OK; int* dimTags = NULL; size_t i, j, c, sz; - struct mem_allocator* allocator; struct scad_device* dev = get_device(); + struct mem_allocator* allocator = dev->allocator; struct htable_tags t2, t3; struct htable_tags_iterator it, end; ASSERT((geometries || !geometries_count) && (out_dimTags || !out_dimTags_n)); - allocator = dev->allocator; htable_tags_init(allocator, &t2); htable_tags_init(allocator, &t3); @@ -172,7 +173,7 @@ gather_tags /* Build result */ sz = htable_tags_size_get(&t2) + htable_tags_size_get(&t3); - dimTags = malloc(sizeof(*dimTags) * sz * 2); + dimTags = MEM_ALLOC(allocator, sz * 2 * sizeof(*dimTags)); if(!dimTags) { res = RES_MEM_ERR; goto error; @@ -203,10 +204,30 @@ exit: htable_tags_release(&t3); return res; error: - free(dimTags); + MEM_RM(allocator, dimTags); goto exit; } +/* gmsh documentation states that memory allocated by gmsh should be freed using + * gmshFree. + * According to valgrind map results as allocated by gmsh are not fully freed if + * simply freed using gmshFree. + * A code review shows that maps content is recursivelly allocated. + * We end writting this helper function that free maps content and makes + * valgrind happy. */ +static void +free_gmsh_map + (int** map, + size_t mapnn) +{ + size_t i; + if(!mapnn) return; + for(i = 0; i < mapnn; i++) { + gmshFree(map[i]); + } + gmshFree(map); +} + /******************************************************************************* * Local functions ******************************************************************************/ @@ -214,24 +235,24 @@ res_T geometry_release (struct scad_geometry* geom) { - struct mem_allocator* allocator; struct scad_device* dev = get_device(); + struct mem_allocator* allocator = dev->allocator; res_T res = RES_OK; size_t n; - ASSERT(geom); (void)n; - allocator = dev->allocator; + ASSERT(geom); + dev->need_synchro = 1; ERR(device_unregister_tags(geom)); - free(geom->gmsh_dimTags); + MEM_RM(allocator, geom->gmsh_dimTags); if(str_len(&geom->name) != 0) { n = htable_names_erase(&dev->geometry_names, &geom->name); ASSERT(n == 1); } str_release(&geom->name); n = htable_geometries_erase(&dev->allgeom, &geom); - ASSERT(n == 1); + ASSERT(n == 1); (void)n; MEM_RM(allocator, geom); end: @@ -273,13 +294,15 @@ scad_scene_clear struct htable_geometries tmp; struct htable_geometries_iterator it, end; struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; int log; ERR(check_device(FUNC_NAME)); + allocator = dev->allocator; log = dev->options.Misc.LogOpenCascadeTagsRefCounting; - htable_geometries_init(dev->allocator, &tmp); - CHK(RES_OK == htable_geometries_copy(&tmp, &dev->allgeom)); + htable_geometries_init(allocator, &tmp); + ERR(htable_geometries_copy(&tmp, &dev->allgeom)); htable_geometries_begin(&tmp, &it); htable_geometries_end(&tmp, &end); if(log) { @@ -302,6 +325,7 @@ scad_scene_clear ERR(gmsh_err_to_res_T(ierr)); end: + if(allocator) htable_geometries_release(&tmp); return res; error: goto end; @@ -314,7 +338,10 @@ scad_geometry_get_count { res_T res = RES_OK; - if(!geom || !count) goto error; + if(!geom || !count) { + res = RES_BAD_ARG; + goto error; + } ERR(check_device(FUNC_NAME)); @@ -324,7 +351,6 @@ scad_geometry_get_count exit: return res; error: - res = RES_BAD_ARG; goto exit; } @@ -335,7 +361,10 @@ scad_geometry_get_name { res_T res = RES_OK; - if(!geom || !name) goto error; + if(!geom || !name) { + res = RES_BAD_ARG; + goto error; + } ERR(check_device(FUNC_NAME)); @@ -345,7 +374,6 @@ scad_geometry_get_name exit: return res; error: - res = RES_BAD_ARG; goto exit; } @@ -359,10 +387,13 @@ scad_geometry_get_mass size_t i, count = 0; int* data = NULL; size_t sz = 0; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; if(!geom || !mass) goto error; ERR(check_device(FUNC_NAME)); + allocator = dev->allocator; ASSERT(geom->gmsh_dimTags_n % 2 == 0); count = geom->gmsh_dimTags_n / 2; @@ -381,7 +412,7 @@ scad_geometry_get_mass } exit: - free(data); + if(allocator) MEM_RM(allocator, data); return res; error: res = RES_BAD_ARG; @@ -398,34 +429,40 @@ scad_geometry_get_centerofmass size_t i = 0; int* data = NULL; size_t sz = 0; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; + double* c = NULL; if(!geom || !center || !center_n) goto error; ERR(check_device(FUNC_NAME)); + allocator = dev->allocator; ASSERT(geom->gmsh_dimTags_n % 2 == 0); *center_n = geom->gmsh_dimTags_n / 2; - *center = (double*)malloc(*center_n * 3 * sizeof(double)); + c = (double*)MEM_ALLOC(allocator, *center_n * 3 * sizeof(*center)); + if(!c) { + res = RES_MEM_ERR; + goto error; + } ERR(gather_tags(&geom, 1, &data, &sz)); for(i=0; i<*center_n; ++i) { - double x, y, z; int ierr = 0; - gmshModelOccGetCenterOfMass(data[2*i], data[2*i + 1], &x, &y, &z, &ierr); + gmshModelOccGetCenterOfMass(data[2*i], data[2*i+1], c+3*i, c+3*i+1, c+3*i+2, &ierr); ERR(gmsh_err_to_res_T(ierr)); - (*center)[3*i] = x; - (*center)[3*i + 1] = y; - (*center)[3*i + 2] = z; } exit: - free(data); + *center = c; + if(allocator) MEM_RM(allocator, data); return res; error: res = RES_BAD_ARG; - if(*center) free(*center); + if(allocator) MEM_RM(allocator, c); + c = NULL; goto exit; } @@ -438,6 +475,8 @@ scad_add_rectangle { int ierr, gmsh_ID; struct scad_geometry* geom = NULL; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; res_T res = RES_OK; if(!xyz || !dxdy || !out_geometry) { @@ -446,6 +485,7 @@ scad_add_rectangle } ERR(check_device(FUNC_NAME)); + allocator = dev->allocator; gmsh_ID = gmshModelOccAddRectangle(SPLIT3(xyz), SPLIT2(dxdy), -1, 0, &ierr); ERR(gmsh_err_to_res_T(ierr)); @@ -453,7 +493,7 @@ scad_add_rectangle ERR(scad_geometry_create(name, &geom)); geom->gmsh_dimTags_n = 2; geom->gmsh_dimTags - = malloc(geom->gmsh_dimTags_n * sizeof(*geom->gmsh_dimTags)); + = MEM_ALLOC(allocator, geom->gmsh_dimTags_n * sizeof(*geom->gmsh_dimTags)); if(!geom->gmsh_dimTags) { res = RES_MEM_ERR; goto error; @@ -483,6 +523,8 @@ scad_add_disk { int ierr, gmsh_ID; struct scad_geometry* geom = NULL; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; res_T res = RES_OK; if(!xyz || radius <= 0 || !out_geometry) { @@ -491,6 +533,7 @@ scad_add_disk } ERR(check_device(FUNC_NAME)); + allocator = dev->allocator; gmsh_ID = gmshModelOccAddDisk(SPLIT3(xyz), radius, radius, -1, &ierr); ERR(gmsh_err_to_res_T(ierr)); @@ -498,7 +541,7 @@ scad_add_disk ERR(scad_geometry_create(name, &geom)); geom->gmsh_dimTags_n = 2; geom->gmsh_dimTags - = malloc(geom->gmsh_dimTags_n * sizeof(*geom->gmsh_dimTags)); + = MEM_ALLOC(allocator, geom->gmsh_dimTags_n * sizeof(*geom->gmsh_dimTags)); if(!geom->gmsh_dimTags) { res = RES_MEM_ERR; goto error; @@ -534,6 +577,8 @@ scad_add_polygon int* points = NULL; int* lines = NULL; int loop; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; res_T res = RES_OK; if(!get_position || count < 3 || !out_geometry) { @@ -542,12 +587,15 @@ scad_add_polygon } ERR(check_device(FUNC_NAME)); + allocator = dev->allocator; - points = malloc(count * sizeof(*points)); - if(!points) { + points = MEM_ALLOC(allocator, count * sizeof(*points)); + lines = MEM_ALLOC(allocator, count * sizeof(*lines)); + if(!points || !lines) { res = RES_MEM_ERR; goto error; } + for(i=0; i<count; ++i) { double pos[2]; get_position(i, pos, data); @@ -555,18 +603,11 @@ scad_add_polygon ERR(gmsh_err_to_res_T(ierr)); } - lines = malloc(count * sizeof(*lines)); - if(!lines) { - res = RES_MEM_ERR; - goto error; - } - for(i=0; i<count-1; ++i) { - lines[i] = gmshModelOccAddLine(points[i], points[i+1], -1, &ierr); + for(i=0; i<count; i++) { + size_t end = (i == count-1) ? 0 : i+1; + lines[i] = gmshModelOccAddLine(points[i], points[end], -1, &ierr); ERR(gmsh_err_to_res_T(ierr)); } - /*and the last line*/ - lines[count-1] = gmshModelOccAddLine(points[count-1], points[0], -1, &ierr); - ERR(gmsh_err_to_res_T(ierr)); loop = gmshModelOccAddCurveLoop(lines, count, -1, &ierr); ERR(gmsh_err_to_res_T(ierr)); @@ -576,8 +617,7 @@ scad_add_polygon ERR(scad_geometry_create(name, &geom)); geom->gmsh_dimTags_n = 2; - geom->gmsh_dimTags - = malloc(geom->gmsh_dimTags_n * sizeof(*geom->gmsh_dimTags)); + geom->gmsh_dimTags = MEM_ALLOC(allocator, 2 * sizeof(*geom->gmsh_dimTags)); if(!geom->gmsh_dimTags) { res = RES_MEM_ERR; goto error; @@ -589,8 +629,10 @@ scad_add_polygon exit: if(out_geometry) *out_geometry = geom; - free(points); - free(lines); + if(allocator) { + MEM_RM(allocator, points); + MEM_RM(allocator, lines); + } return res; error: if(geom) { @@ -609,6 +651,8 @@ scad_add_box { int ierr, gmsh_ID; struct scad_geometry* geom = NULL; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; res_T res = RES_OK; if(!xyz || !dxdydz || !out_geometry) { @@ -617,14 +661,14 @@ scad_add_box } ERR(check_device(FUNC_NAME)); + allocator = dev->allocator; gmsh_ID = gmshModelOccAddBox(SPLIT3(xyz), SPLIT3(dxdydz), -1, &ierr); ERR(gmsh_err_to_res_T(ierr)); ERR(scad_geometry_create(name, &geom)); geom->gmsh_dimTags_n = 2; - geom->gmsh_dimTags - = malloc(geom->gmsh_dimTags_n * sizeof(*geom->gmsh_dimTags)); + geom->gmsh_dimTags = MEM_ALLOC(allocator, 2 * sizeof(*geom->gmsh_dimTags)); if(!geom->gmsh_dimTags) { res = RES_MEM_ERR; goto error; @@ -656,6 +700,8 @@ scad_add_cylinder { int ierr, gmsh_ID; struct scad_geometry* geom = NULL; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; res_T res = RES_OK; if(!xyz || !axis || radius <= 0 || angle < 0 || angle > 2*PI || !out_geometry) { @@ -664,6 +710,7 @@ scad_add_cylinder } ERR(check_device(FUNC_NAME)); + allocator = dev->allocator; gmsh_ID = gmshModelOccAddCylinder(SPLIT3(xyz), SPLIT3(axis), radius, -1, angle, &ierr); @@ -671,8 +718,7 @@ scad_add_cylinder ERR(scad_geometry_create(name, &geom)); geom->gmsh_dimTags_n = 2; - geom->gmsh_dimTags - = malloc(geom->gmsh_dimTags_n * sizeof(*geom->gmsh_dimTags)); + geom->gmsh_dimTags = MEM_ALLOC(allocator, 2 * sizeof(*geom->gmsh_dimTags)); if(!geom->gmsh_dimTags) { res = RES_MEM_ERR; goto error; @@ -702,6 +748,8 @@ scad_add_sphere { int ierr, gmsh_ID; struct scad_geometry* geom = NULL; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; res_T res = RES_OK; if(!xyz || radius <= 0 || !out_geometry) { @@ -710,6 +758,7 @@ scad_add_sphere } ERR(check_device(FUNC_NAME)); + allocator = dev->allocator; gmsh_ID = gmshModelOccAddSphere(SPLIT3(xyz), radius, -1, -PI/2, PI/2, 2*PI, &ierr); @@ -717,8 +766,7 @@ scad_add_sphere ERR(scad_geometry_create(name, &geom)); geom->gmsh_dimTags_n = 2; - geom->gmsh_dimTags - = malloc(geom->gmsh_dimTags_n * sizeof(*geom->gmsh_dimTags)); + geom->gmsh_dimTags = MEM_ALLOC(allocator, 2 * sizeof(*geom->gmsh_dimTags)); if(!geom->gmsh_dimTags) { res = RES_MEM_ERR; goto error; @@ -751,11 +799,13 @@ scad_fuse_geometries int* tagout = NULL; int** map = NULL; size_t* mapn = NULL; - size_t tagoutn, mapnn, sz1, sz2; + size_t tagoutn, mapnn = 0, sz1, sz2; int* data1 = NULL; int* data2 = NULL; int ierr = 0; struct scad_geometry* geom = NULL; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; res_T res = RES_OK; if(!geometries || !geometries_count || !tools || !tools_count || !out_geometry) { @@ -767,6 +817,7 @@ scad_fuse_geometries if(get_device()->need_synchro) { ERR(scad_synchronize()); } + allocator = dev->allocator; ERR(gather_tags(geometries, geometries_count, &data1, &sz1)); ERR(gather_tags(tools, tools_count, &data2, &sz2)); @@ -779,27 +830,31 @@ scad_fuse_geometries ERR(scad_geometry_create(name, &geom)); geom->gmsh_dimTags_n = tagoutn; - geom->gmsh_dimTags = tagout; - tagout = NULL; /* Prevent possible double free */ + geom->gmsh_dimTags = MEM_ALLOC(allocator, tagoutn * sizeof(*tagout)); + if(!geom->gmsh_dimTags) { + res = RES_MEM_ERR; + goto error; + } + memcpy(geom->gmsh_dimTags, tagout, tagoutn * sizeof(*tagout)); ERR(device_register_tags(geom)); exit: if(out_geometry) *out_geometry = geom; - free(data1); - free(data2); - free(mapn); - free(map); + if(allocator) { + MEM_RM(allocator, data1); + MEM_RM(allocator, data2); + } + gmshFree(mapn); + gmshFree(tagout); + free_gmsh_map(map, mapnn); return res; error: if(geom) { CHK(RES_OK == geometry_release(geom)); geom = NULL; } - if(tagout) { - gmshModelOccRemove(tagout, tagoutn, 1, &ierr); - free(tagout); - } + if(tagout) gmshModelOccRemove(tagout, tagoutn, 1, &ierr); goto exit; } @@ -815,11 +870,13 @@ scad_cut_geometries int* tagout = NULL; int** map = NULL; size_t* mapn = NULL; - size_t tagoutn, mapnn, sz1, sz2; + size_t tagoutn, mapnn = 0, sz1, sz2; int* data1 = NULL; int* data2 = NULL; int ierr = 0; struct scad_geometry* geom = NULL; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; res_T res = RES_OK; if(!geometries || !geometries_count || !tools || !tools_count || !out_geometry) { @@ -831,6 +888,7 @@ scad_cut_geometries if(get_device()->need_synchro) { ERR(scad_synchronize()); } + allocator = dev->allocator; ERR(gather_tags(geometries, geometries_count, &data1, &sz1)); ERR(gather_tags(tools, tools_count, &data2, &sz2)); @@ -843,27 +901,31 @@ scad_cut_geometries ERR(scad_geometry_create(name, &geom)); geom->gmsh_dimTags_n = tagoutn; - geom->gmsh_dimTags = tagout; - tagout = NULL; /* Prevent possible double free */ + geom->gmsh_dimTags = MEM_ALLOC(allocator, tagoutn * sizeof(*tagout)); + if(!geom->gmsh_dimTags) { + res = RES_MEM_ERR; + goto error; + } + memcpy(geom->gmsh_dimTags, tagout, tagoutn * sizeof(*tagout)); ERR(device_register_tags(geom)); exit: if(out_geometry) *out_geometry = geom; - free(data1); - free(data2); - free(mapn); - free(map); + if(allocator) { + MEM_RM(allocator, data1); + MEM_RM(allocator, data2); + } + gmshFree(mapn); + gmshFree(tagout); + free_gmsh_map(map, mapnn); return res; error: if(geom) { CHK(RES_OK == geometry_release(geom)); geom = NULL; } - if(tagout) { - gmshModelOccRemove(tagout, tagoutn, 1, &ierr); - free(tagout); - } + if(tagout) gmshModelOccRemove(tagout, tagoutn, 1, &ierr); goto exit; } @@ -879,11 +941,13 @@ scad_intersect_geometries int* tagout = NULL; int** map = NULL; size_t* mapn = NULL; - size_t tagoutn, mapnn, sz1, sz2; + size_t tagoutn, mapnn = 0, sz1, sz2; int* data1 = NULL; int* data2 = NULL; int ierr = 0; struct scad_geometry* geom = NULL; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; res_T res = RES_OK; if(!geometries || !geometries_count || !tools || !tools_count || !out_geometry) { @@ -895,6 +959,7 @@ scad_intersect_geometries if(get_device()->need_synchro) { ERR(scad_synchronize()); } + allocator = dev->allocator; ERR(gather_tags(geometries, geometries_count, &data1, &sz1)); ERR(gather_tags(tools, tools_count, &data2, &sz2)); @@ -907,27 +972,31 @@ scad_intersect_geometries ERR(scad_geometry_create(name, &geom)); geom->gmsh_dimTags_n = tagoutn; - geom->gmsh_dimTags = tagout; - tagout = NULL; /* Prevent possible double free */ + geom->gmsh_dimTags = MEM_ALLOC(allocator, tagoutn * sizeof(*tagout)); + if(!geom->gmsh_dimTags) { + res = RES_MEM_ERR; + goto error; + } + memcpy(geom->gmsh_dimTags, tagout, tagoutn * sizeof(*tagout)); ERR(device_register_tags(geom)); exit: if(out_geometry) *out_geometry = geom; - free(data1); - free(data2); - free(mapn); - free(map); + if(allocator) { + MEM_RM(allocator, data1); + MEM_RM(allocator, data2); + } + gmshFree(mapn); + gmshFree(tagout); + free_gmsh_map(map, mapnn); return res; error: if(geom) { CHK(RES_OK == geometry_release(geom)); geom = NULL; } - if(tagout) { - gmshModelOccRemove(tagout, tagoutn, 1, &ierr); - free(tagout); - } + if(tagout) gmshModelOccRemove(tagout, tagoutn, 1, &ierr); goto exit; } @@ -943,7 +1012,7 @@ scad_geometries_common_boundaries int* tagout = NULL; int** map = NULL; size_t* mapn = NULL; - size_t tagoutn, mapnn, sz1, sz2; + size_t tagoutn, mapnn = 0, sz1, sz2; int* data1 = NULL; int* data2 = NULL; int ierr = 0; @@ -951,6 +1020,8 @@ scad_geometries_common_boundaries int* bound2 = NULL; size_t n1, n2; struct scad_geometry* geom = NULL; + struct mem_allocator* allocator = NULL; + struct scad_device* dev = get_device(); res_T res = RES_OK; if(!geometries || !geometries_count || !tools || !tools_count || !out_geometry) { @@ -962,6 +1033,7 @@ scad_geometries_common_boundaries if(get_device()->need_synchro) { ERR(scad_synchronize()); } + allocator = dev->allocator; ERR(gather_tags(geometries, geometries_count, &data1, &sz1)); ERR(gather_tags(tools, tools_count, &data2, &sz2)); @@ -978,29 +1050,33 @@ scad_geometries_common_boundaries ERR(scad_geometry_create(name, &geom)); geom->gmsh_dimTags_n = tagoutn; - geom->gmsh_dimTags = tagout; - tagout = NULL; /* Prevent possible double free */ + geom->gmsh_dimTags = MEM_ALLOC(allocator, tagoutn * sizeof(*tagout)); + if(!geom->gmsh_dimTags) { + res = RES_MEM_ERR; + goto error; + } + memcpy(geom->gmsh_dimTags, tagout, tagoutn * sizeof(*tagout)); ERR(device_register_tags(geom)); exit: if(out_geometry) *out_geometry = geom; - free(data1); - free(data2); - free(bound1); - free(bound2); - free(mapn); - free(map); + if(allocator) { + MEM_RM(allocator, data1); + MEM_RM(allocator, data2); + } + gmshFree(bound1); + gmshFree(bound2); + gmshFree(mapn); + gmshFree(tagout); + free_gmsh_map(map, mapnn); return res; error: if(geom) { CHK(RES_OK == geometry_release(geom)); geom = NULL; } - if(tagout) { - gmshModelOccRemove(tagout, tagoutn, 1, &ierr); - free(tagout); - } + if(tagout) gmshModelOccRemove(tagout, tagoutn, 1, &ierr); goto exit; } @@ -1047,12 +1123,13 @@ scad_geometry_extrude { int* tagout = NULL; size_t tagoutn; - int* data; - size_t i, j, sz; + size_t i, j; int* extrude_data = NULL; size_t extrude_sz = 0; int ierr = 0; struct scad_geometry* extrude_geom = NULL; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; res_T res = RES_OK; if(!geom || !dxdydz || !out_geometry) { @@ -1064,42 +1141,43 @@ scad_geometry_extrude if(get_device()->need_synchro) { ERR(scad_synchronize()); } + allocator = dev->allocator; - sz = geom->gmsh_dimTags_n; - data = geom->gmsh_dimTags; - gmshModelOccExtrude(data, sz, SPLIT3(dxdydz), &tagout, &tagoutn, - NULL, 0, NULL, 0, 0, &ierr); + gmshModelOccExtrude(geom->gmsh_dimTags, geom->gmsh_dimTags_n, SPLIT3(dxdydz), + &tagout, &tagoutn, NULL, 0, NULL, 0, 0, &ierr); get_device()->need_synchro = 1; ERR(gmsh_err_to_res_T(ierr)); ERR(scad_geometry_create(name, &extrude_geom)); /* keep only 3D entities */ /* TODO : NOT SURE OF THE CONCEPT */ - for(i=0; i<tagoutn/2; ++i) { - if(tagout[2*i] == 3) extrude_sz += 2; + for(i=0; i<tagoutn; i+=2) { + int dim = tagout[i]; + if(dim == 3) extrude_sz += 2; } - extrude_data = malloc(extrude_sz * sizeof(*extrude_data)); + extrude_data = MEM_ALLOC(allocator, extrude_sz * sizeof(*extrude_data)); if(!extrude_data) { res = RES_MEM_ERR; goto error; } j = 0; - for(i=0; i<tagoutn/2; ++i) { - if(tagout[2*i] == 3) { - extrude_data[2*j] = 3; - extrude_data[2*j+1] = tagout[2*i+1]; - ++j; + for(i=0; i<tagoutn; i+=2) { + int dim = tagout[i]; + int tag = tagout[i+1]; + if(dim == 3) { + extrude_data[j] = dim; + extrude_data[j+1] = tag; + j += 2; } } + ASSERT(j == extrude_sz); extrude_geom->gmsh_dimTags_n = extrude_sz; extrude_geom->gmsh_dimTags = extrude_data; - tagout = NULL; /* Prevent possible double free */ - ERR(device_register_tags(extrude_geom)); exit: if(out_geometry) *out_geometry = extrude_geom; - free(tagout); + gmshFree(tagout); return res; error: if(extrude_geom) { @@ -1122,29 +1200,32 @@ scad_geometry_explode struct scad_geometry** geom_array = NULL; struct str name; int name_initialized = 0; - - ERR(check_device(FUNC_NAME)); - if(get_device()->need_synchro) { - ERR(scad_synchronize()); - } + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; if(!geom || !out_geometry || !out_geometry_n) { res = RES_BAD_ARG; goto error; } + ERR(check_device(FUNC_NAME)); + if(dev->need_synchro) { + ERR(scad_synchronize()); + } + allocator = dev->allocator; + data = geom->gmsh_dimTags; sz = geom->gmsh_dimTags_n; ASSERT(sz % 2 == 0); - geom_array = malloc(sz/2 * sizeof(*geom_array)); + geom_array = MEM_CALLOC(allocator, sz/2, sizeof(*geom_array)); if(!geom_array) { res = RES_MEM_ERR; goto error; } if(prefix_name) { - str_init(get_device()->allocator, &name); + str_init(allocator, &name); name_initialized = 1; } for(i=0; i<sz/2; ++i) { @@ -1156,8 +1237,8 @@ scad_geometry_explode ERR(scad_geometry_create(NULL, geom_array+i)); } geom_array[i]->gmsh_dimTags_n = 2; - geom_array[i]->gmsh_dimTags = malloc(geom_array[i]->gmsh_dimTags_n * - sizeof(*geom_array[i]->gmsh_dimTags)); + geom_array[i]->gmsh_dimTags + = MEM_ALLOC(allocator, 2 * sizeof(*geom_array[i]->gmsh_dimTags)); if(!geom_array[i]->gmsh_dimTags) { res = RES_MEM_ERR; goto error; @@ -1175,7 +1256,10 @@ exit: return res; error: if(geom_array) { - free(geom_array); + for(i = 0; i < sz/2; i++) { + if(geom_array[i]) SCAD(geometry_delete(geom_array[i])); + } + MEM_RM(allocator, geom_array); geom_array = NULL; } goto exit; @@ -1193,6 +1277,8 @@ scad_geometry_copy size_t sz1, tagoutn; int ierr = 0; struct scad_geometry* copy = NULL; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; res_T res = RES_OK; if(!geom || !out_geometry) { @@ -1204,6 +1290,7 @@ scad_geometry_copy if(get_device()->need_synchro) { ERR(scad_synchronize()); } + allocator = dev->allocator; sz1 = geom->gmsh_dimTags_n; data1 = geom->gmsh_dimTags; @@ -1213,23 +1300,25 @@ scad_geometry_copy ERR(scad_geometry_create(name, &copy)); copy->gmsh_dimTags_n = tagoutn; - copy->gmsh_dimTags = tagout; - tagout = NULL; /* Prevent possible double free */ + copy->gmsh_dimTags = MEM_ALLOC(allocator, tagoutn * sizeof(*tagout)); + if(!copy->gmsh_dimTags) { + res = RES_MEM_ERR; + goto error; + } + memcpy(copy->gmsh_dimTags, tagout, tagoutn * sizeof(*tagout)); ERR(device_register_tags(copy)); exit: if(out_geometry) *out_geometry = copy; + gmshFree(tagout); return res; error: if(copy) { CHK(RES_OK == geometry_release(copy)); copy = NULL; } - if(tagout) { - gmshModelOccRemove(tagout, tagoutn, 1, &ierr); - free(tagout); - } + if(tagout) gmshModelOccRemove(tagout, tagoutn, 1, &ierr); goto exit; } @@ -1309,6 +1398,7 @@ scad_geometries_partition struct htable_tags t2, t3; struct htable_tags_iterator it, end; int ht_initialized = 0; + struct mem_allocator* allocator = NULL; if(!geometries || !geometries_count || (allow_overlapping && !out_geometries)) { res = RES_BAD_ARG; @@ -1319,6 +1409,7 @@ scad_geometries_partition if(get_device()->need_synchro) { ERR(scad_synchronize()); } + allocator = dev->allocator; ERR(gather_tags(geometries, geometries_count, &data, &sz)); @@ -1358,7 +1449,6 @@ scad_geometries_partition } if(res != RES_OK) goto error; } else { - struct mem_allocator* allocator = dev->allocator; /* Create htables of mappings to ease access */ htable_mappings_init(allocator, &m2); htable_mappings_init(allocator, &m3); @@ -1373,7 +1463,7 @@ scad_geometries_partition } /* Create output geometries from mapping */ - geoms = calloc(geometries_count, sizeof(*geoms)); + geoms = MEM_CALLOC(allocator, geometries_count, sizeof(*geoms)); if(!geoms) { res = RES_MEM_ERR; goto error; @@ -1407,7 +1497,7 @@ scad_geometries_partition } /* Allocate result */ n = htable_tags_size_get(&t2) + htable_tags_size_get(&t3); - dt = malloc(sizeof(*dt) * 2 * n); + dt = MEM_ALLOC(allocator, sizeof(*dt) * 2 * n); if(!dt) { res = RES_MEM_ERR; goto error; @@ -1440,8 +1530,8 @@ scad_geometries_partition } exit: - for(i = 0; i < mapnn; i++) free(map[i]); - free(mapn); + gmshFree(mapn); + free_gmsh_map(map, mapnn); if(hm_initialized) { htable_mappings_release(&m2); htable_mappings_release(&m3); @@ -1450,9 +1540,11 @@ exit: htable_tags_release(&t2); htable_tags_release(&t3); } - free(geoms); - free(data); - free(tagout); + if(allocator) { + MEM_RM(allocator, data); + MEM_RM(allocator, geoms); + } + gmshFree(tagout); return res; error: if(geoms) { @@ -1478,11 +1570,13 @@ scad_fragment_geometries int* tagout = NULL; int** map = NULL; size_t* mapn = NULL; - size_t tagoutn, mapnn, sz1, sz2; + size_t tagoutn, mapnn = 0, sz1, sz2; int* data1 = NULL; int* data2 = NULL; int ierr = 0; struct scad_geometry* geom = NULL; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; res_T res = RES_OK; if(!geometries || !geometries_count || !tools || !tools_count || !out_geometry) { @@ -1494,6 +1588,7 @@ scad_fragment_geometries if(get_device()->need_synchro) { ERR(scad_synchronize()); } + allocator = dev->allocator; ERR(gather_tags(geometries, geometries_count, &data1, &sz1)); ERR(gather_tags(tools, tools_count, &data2, &sz2)); @@ -1506,27 +1601,31 @@ scad_fragment_geometries ERR(scad_geometry_create(name, &geom)); geom->gmsh_dimTags_n = tagoutn; - geom->gmsh_dimTags = tagout; - tagout = NULL; /* Prevent possible double free */ + geom->gmsh_dimTags = MEM_ALLOC(allocator, tagoutn * sizeof(*tagout)); + if(!geom->gmsh_dimTags) { + res = RES_MEM_ERR; + goto error; + } + memcpy(geom->gmsh_dimTags, tagout, tagoutn * sizeof(*tagout)); ERR(device_register_tags(geom)); exit: if(out_geometry) *out_geometry = geom; - free(data1); - free(data2); - free(mapn); - free(map); + if(allocator) { + MEM_RM(allocator, data1); + MEM_RM(allocator, data2); + } + gmshFree(mapn); + gmshFree(tagout); + free_gmsh_map(map, mapnn); return res; error: if(geom) { CHK(RES_OK == geometry_release(geom)); geom = NULL; } - if(tagout) { - gmshModelOccRemove(tagout, tagoutn, 1, &ierr); - free(tagout); - } + if(tagout) gmshModelOccRemove(tagout, tagoutn, 1, &ierr); goto exit; } @@ -1544,6 +1643,8 @@ scad_geometry_boundary int* data = NULL; int ierr = 0; struct scad_geometry* geom = NULL; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; res_T res = RES_OK; if(!geometries || !out_geometry) { @@ -1551,9 +1652,11 @@ scad_geometry_boundary goto error; } + ERR(check_device(FUNC_NAME)); if(get_device()->need_synchro) { ERR(scad_synchronize()); } + allocator = dev->allocator; ERR(gather_tags(geometries, geometries_count, &data, &sz)); gmshModelGetBoundary(data, sz, &tagout, &tagoutn, 1, 0, 0, &ierr); @@ -1561,24 +1664,26 @@ scad_geometry_boundary ERR(scad_geometry_create(name, &geom)); geom->gmsh_dimTags_n = tagoutn; - geom->gmsh_dimTags = tagout; - tagout = NULL; /* Prevent possible double free */ + geom->gmsh_dimTags = MEM_ALLOC(allocator, tagoutn * 2 * sizeof(*tagout)); + if(!geom->gmsh_dimTags) { + res = RES_MEM_ERR; + goto error; + } + memcpy(geom->gmsh_dimTags, tagout, tagoutn * sizeof(*tagout)); ERR(device_register_tags(geom)); exit: - free(data); + if(allocator) MEM_RM(allocator, data); if(out_geometry) *out_geometry = geom; + gmshFree(tagout); return res; error: if(geom) { CHK(RES_OK == geometry_release(geom)); geom = NULL; } - if(tagout) { - gmshModelOccRemove(tagout, tagoutn, 1, &ierr); - free(tagout); - } + if(tagout) gmshModelOccRemove(tagout, tagoutn, 1, &ierr); goto exit; } @@ -1595,6 +1700,8 @@ scad_step_import struct str strname; int name_initialized = 0; struct scad_geometry** geom_array = NULL; + struct mem_allocator* allocator = NULL; + struct scad_device* dev = get_device(); res_T res = RES_OK; if(!filename || !name || !out_geometry || !out_geometry_n) { @@ -1606,19 +1713,21 @@ scad_step_import if(get_device()->need_synchro) { ERR(scad_synchronize()); } + allocator = dev->allocator; gmshModelOccImportShapes(filename, &tagout, &tagoutn, 1, "step", &ierr); ERR(gmsh_err_to_res_T(ierr)); ASSERT(tagoutn % 2 == 0); ga_sz = tagoutn / 2; - geom_array = malloc(ga_sz * sizeof(*geom_array)); + allocator = get_device()->allocator; + geom_array = MEM_CALLOC(allocator, ga_sz, sizeof(*geom_array)); if(!geom_array) { res = RES_MEM_ERR; goto error; } - str_init(get_device()->allocator, &strname); + str_init(allocator, &strname); name_initialized = 1; for(i=0; i<ga_sz; ++i) { ERR(str_set(&strname, name)); @@ -1626,8 +1735,8 @@ scad_step_import ERR(scad_geometry_create(str_cget(&strname), geom_array+i)); geom_array[i]->gmsh_dimTags_n = 2; - geom_array[i]->gmsh_dimTags = malloc(geom_array[i]->gmsh_dimTags_n * - sizeof(*geom_array[i]->gmsh_dimTags)); + geom_array[i]->gmsh_dimTags + = MEM_ALLOC(allocator, 2 * sizeof(*geom_array[i]->gmsh_dimTags)); if(!geom_array[i]->gmsh_dimTags) { res = RES_MEM_ERR; goto error; @@ -1639,18 +1748,19 @@ scad_step_import } exit: + gmshFree(tagout); if(out_geometry_n) *out_geometry_n = ga_sz ; if(out_geometry) *out_geometry = geom_array; if(name_initialized) str_release(&strname); return res; error: - if(tagout) { - gmshModelOccRemove(tagout, tagoutn, 1, &ierr); - free(tagout); - } + if(tagout) gmshModelOccRemove(tagout, tagoutn, 1, &ierr); ga_sz = 0; if(geom_array) { - free(geom_array); + for(i=0; i<ga_sz; ++i) { + if(geom_array[i]) SCAD(geometry_delete(geom_array[i])); + } + MEM_RM(allocator, geom_array); geom_array = NULL; } goto exit; @@ -1672,6 +1782,8 @@ scad_geometry_normal size_t sz = 0; struct scad_geometry* surface = NULL; struct scad_geometry* out = NULL; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; if(!geom || !p || !N || !out_geometry) { res = RES_BAD_ARG; @@ -1679,6 +1791,7 @@ scad_geometry_normal } ERR(check_device(FUNC_NAME)); + allocator = dev->allocator; if(geom->gmsh_dimTags[0] == 2) { ERR(scad_geometry_copy(geom, NULL, &surface)); @@ -1693,46 +1806,47 @@ scad_geometry_normal ERR(gather_tags(&surface, 1, &data, &sz)); for(i=0; sz/2; ++i) { - double* coord; - double* pcoord; - size_t pcoord_n; - size_t coord_n; - double* normals; - size_t normals_n; - - gmshModelGetParametrization(2, data[2*i + 1], p, 3, &pcoord, &pcoord_n, &ierr); - ERR(gmsh_err_to_res_T(ierr)); + double* coord = NULL; + double* pcoord = NULL; + size_t pcoord_n; + size_t coord_n; + double* normals = NULL; + size_t normals_n; + int dim = data[2*i]; + int tag = data[2*i + 1]; + + gmshModelGetParametrization(2, tag, p, 3, &pcoord, &pcoord_n, &ierr); + ERR(gmsh_err_to_res_T(ierr)); + + gmshModelGetValue(2, tag, pcoord, pcoord_n, &coord, &coord_n, &ierr); + ERR(gmsh_err_to_res_T(ierr)); - gmshModelGetValue(2, - data[2*i + 1], - pcoord, pcoord_n, - &coord, &coord_n, - &ierr); + if(d3_eq_eps(p, coord, 1e-6)) { + gmshModelGetNormal(tag, pcoord, pcoord_n, &normals, &normals_n, &ierr); ERR(gmsh_err_to_res_T(ierr)); - if(d3_eq_eps(p, coord, 1e-6)) { - gmshModelGetNormal(data[2*i + 1], pcoord, pcoord_n, - &normals, &normals_n, &ierr); - ERR(gmsh_err_to_res_T(ierr)); - - ERR(scad_geometry_create(name, &out)); - out->gmsh_dimTags = (int*)malloc(2*sizeof(int)); - out->gmsh_dimTags_n = 2; - out->gmsh_dimTags[0] = data[2*i]; - out->gmsh_dimTags[1] = data[2*i+1]; - ERR(device_register_tags(out)); - - d3_set(N, normals); - if(coord) free(coord); - if(pcoord) free(pcoord); - if(normals) free(normals); - break; + ERR(scad_geometry_create(name, &out)); + out->gmsh_dimTags = MEM_ALLOC(allocator, 2 * sizeof(*out->gmsh_dimTags)); + if(!out->gmsh_dimTags) { + res = RES_MEM_ERR; + goto error; } + out->gmsh_dimTags_n = 2; + out->gmsh_dimTags[0] = dim; + out->gmsh_dimTags[1] = tag; + ERR(device_register_tags(out)); + + d3_set(N, normals); + gmshFree(coord); + gmshFree(pcoord); + gmshFree(normals); + break; + } } exit: if(out_geometry) *out_geometry = out; - free(data); + if(allocator) MEM_RM(allocator, data); if(surface) scad_geometry_delete(surface); return res; error: @@ -1749,6 +1863,8 @@ scad_geometry_dilate int ierr = 0; int* data = NULL; size_t sz = 0; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = NULL; if(!geom || !scale|| !center) { res = RES_BAD_ARG; @@ -1756,6 +1872,7 @@ scad_geometry_dilate } ERR(check_device(FUNC_NAME)); + allocator = dev->allocator; ERR(gather_tags(&geom, 1, &data, &sz)); @@ -1763,7 +1880,7 @@ scad_geometry_dilate ERR(gmsh_err_to_res_T(ierr)); exit: - if(data) free(data); + if(allocator) MEM_RM(allocator, data); return res; error: goto exit;