Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use calloc for potentially large user-defined inputs #100

Merged
merged 1 commit into from
Jul 30, 2018

Conversation

isaachier
Copy link
Contributor

No description provided.

@coveralls
Copy link

coveralls commented Jul 25, 2018

Coverage Status

Coverage remained the same at 100.0% when pulling 70a099f on isaachier:calloc-large-arrays into e506b81 on uber:master.

Copy link
Collaborator

@dfellis dfellis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you so much for doing this, @isaachier 😃

@isaachier
Copy link
Contributor Author

Np thanks for pointing this out @dfellis. 😄

Copy link
Collaborator

@nrabinowitz nrabinowitz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, are we sure it covers all cases? I'd imagine we'd be most concerned with arrays of hexagons.

@@ -791,7 +792,7 @@ void H3_EXPORT(polyfill)(const GeoPolygon* geoPolygon, int res, H3Index* out) {
// This first part is identical to the maxPolyfillSize above.

// Get the bounding boxes for the polygon and any holes
STACK_ARRAY_CALLOC(BBox, bboxes, geoPolygon->numHoles + 1);
BBox* bboxes = calloc(geoPolygon->numHoles + 1, sizeof(BBox));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this one's a risk - it scales with the number of polygons, not the number of hexagons, and should be fine with stack allocation.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I say better safe than sorry here. What if someone provides a geofence of the US, but just does it lazily by shoving in all of the county geofences in a huge array? (Or attempting to guarantee exact set matching if they need national and county level hexagon sets as a more rational explanation.)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Point taken. I didn't realize we were removing all instances of STACK_ARRAY_CALLOC, in which case sure. No real preference here.

@dfellis
Copy link
Collaborator

dfellis commented Jul 25, 2018

@nrabinowitz

LGTM, are we sure it covers all cases? I'd imagine we'd be most concerned with arrays of hexagons.

So I'm pretty sure @isaachier has removed all uses of STACK_ARRAY_CALLOC from the actual library. It's now used only in some of the apps.

damocles@Talyn:~/oss/h3/src/h3lib(master)$ git grep STACK_ARRAY_CALLOC
include/stackAlloc.h:#define STACK_ARRAY_CALLOC(type, name, numElements)        \
include/stackAlloc.h:#define STACK_ARRAY_CALLOC(type, name, numElements)            \
include/stackAlloc.h:#define STACK_ARRAY_CALLOC(type, name, numElements)           \
lib/algos.c:    STACK_ARRAY_CALLOC(int, distances, maxIdx);
lib/algos.c:    STACK_ARRAY_CALLOC(BBox, bboxes, geoPolygon->numHoles + 1);
lib/h3Index.c:    STACK_ARRAY_CALLOC(H3Index, remainingHexes, numHexes);
lib/h3Index.c:    STACK_ARRAY_CALLOC(H3Index, hashSetArray, numHexes);
lib/h3Index.c:        STACK_ARRAY_CALLOC(H3Index, compactableHexes, maxCompactableCount);

Two uses in algos.c and three in h3Index.c, and that's how many changes I count in his PR. :)

So the only stack allocations are now constant amounts of memory, which is much safer. (It would be nice if we could eliminate all arbitrary memory allocations from the library and let the user decide on stack vs heap allocation themselves, but that would require some API changes and some awkward API usage patterns, where some blocks of memory are requested to be freed immediately by the user of the API.)

@isaachier
Copy link
Contributor Author

@dfellis many C libraries let you override the default allocator. Here's an example from one of my favorite C libraries, Jansson:

https://github.com/akheron/jansson/blob/aed855e6920923898b94a1b922fbace27a34ddf2/src/jansson.h#L355-L361:

/* custom memory allocation */

typedef void *(*json_malloc_t)(size_t);
typedef void (*json_free_t)(void *);

void json_set_alloc_funcs(json_malloc_t malloc_fn, json_free_t free_fn);
void json_get_alloc_funcs(json_malloc_t *malloc_fn, json_free_t *free_fn);

It just stores a custom malloc and free in static variables and uses those across the board. That allows users to implement custom allocators.

@dfellis
Copy link
Collaborator

dfellis commented Jul 25, 2018

Something to consider, but that proposed implementation wouldn't be threadsafe if you want to choose the allocator based on the function call or data volume. Go too far and we'll start reimplementing C++. 😉

@isaachier
Copy link
Contributor Author

You can always use pthreads... but I get the point. Globals aren't straightforward.

@isaachier isaachier force-pushed the calloc-large-arrays branch from e978d55 to 70a099f Compare July 29, 2018 03:01
@isaacbrodsky isaacbrodsky merged commit 06bf785 into uber:master Jul 30, 2018
@isaachier isaachier deleted the calloc-large-arrays branch August 2, 2018 16:13
@willcohen willcohen mentioned this pull request Aug 3, 2018
mrdvt92 pushed a commit to mrdvt92/h3 that referenced this pull request Jun 19, 2022
Use calloc for potentially large user-defined inputs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants