Hello: I wish to report a potential memory leak in GEOSTopologyPreserveSimplify. This memory leak appears serious enough that my batch processing software will run out of memory a few minutes into its processing.
This is with geos-3.0.0 on Mac OS X 10.4.11. The library has been configured and made without any special options: ./configure --prefix=<somedir>/.install; make; make install I have modified the capi/geostest.c program to demonstrate the problem. The file is included at the end of this mail. I have used standard Mac OS X tools to track the memory leak: MallocStackLogging=1 ./a.out test.wkt Using Mac OS X's /usr/bin/leaks tool and after some post-processing I get as output the call stacks of the allocation point of leaked objects. This output is included at the end of this mail. Looking at the output it appears that (among others) geos::index::quadtree::Node::NodeBase objects get created but never freed. My knowledge of the GEOS internals is 0, so I am turning to this list in the hope that the matter can be resolved. Many thanks for your help and attention. Please note that I am not subscribed to the geos-devel list so CC me on any responses. Bill leaks: << start | _start | main | do_all | GEOSTopologyPreserveSimplify | geos::simplify::TopologyPreservingSimplifier::simplify(geos::geom::Geometry const*, double) | geos::simplify::TopologyPreservingSimplifier::getResultGeometry() | geos::simplify::LineSegmentIndex::add(geos::simplify::TaggedLineString const&) | geos::simplify::LineSegmentIndex::add(geos::geom::LineSegment const*) | geos::index::quadtree::Quadtree::insert(geos::geom::Envelope const*, void*) | geos::index::quadtree::Root::insert(geos::geom::Envelope const*, void*) | geos::index::quadtree::NodeBase::add(void*) | std::vector<void*, std::allocator<void*> >::_M_insert_aux(__gnu_cxx::__normal_iterator<void**, std::vector<void*, std::allocator<void*> > >, void* const&) | operator new(unsigned long) | malloc start | _start | main | do_all | GEOSTopologyPreserveSimplify | geos::simplify::TopologyPreservingSimplifier::simplify(geos::geom::Geometry const*, double) | geos::simplify::TopologyPreservingSimplifier::getResultGeometry() | geos::simplify::LineSegmentIndex::add(geos::simplify::TaggedLineString const&) | geos::simplify::LineSegmentIndex::add(geos::geom::LineSegment const*) | geos::index::quadtree::Quadtree::insert(geos::geom::Envelope const*, void*) | geos::index::quadtree::Root::insert(geos::geom::Envelope const*, void*) | geos::index::quadtree::Root::insertContained(geos::index::quadtree::Node*, geos::geom::Envelope const*, void*) | geos::index::quadtree::Node::getNode(geos::geom::Envelope const*) | geos::index::quadtree::Node::getSubnode(int) | geos::index::quadtree::Node::createSubnode(int) | geos::index::quadtree::NodeBase::NodeBase[not-in-charge]() | operator new(unsigned long) | malloc start | _start | main | do_all | GEOSTopologyPreserveSimplify | geos::simplify::TopologyPreservingSimplifier::simplify(geos::geom::Geometry const*, double) | geos::simplify::TopologyPreservingSimplifier::getResultGeometry() | geos::simplify::LineSegmentIndex::add(geos::simplify::TaggedLineString const&) | geos::simplify::LineSegmentIndex::add(geos::geom::LineSegment const*) | geos::index::quadtree::Quadtree::insert(geos::geom::Envelope const*, void*) | geos::index::quadtree::Root::insert(geos::geom::Envelope const*, void*) | geos::index::quadtree::Root::insertContained(geos::index::quadtree::Node*, geos::geom::Envelope const*, void*) | geos::index::quadtree::Node::getNode(geos::geom::Envelope const*) | geos::index::quadtree::Node::getSubnode(int) | geos::index::quadtree::Node::createSubnode(int) | operator new(unsigned long) | malloc start | _start | main | do_all | GEOSTopologyPreserveSimplify | geos::simplify::TopologyPreservingSimplifier::simplify(geos::geom::Geometry const*, double) | geos::simplify::TopologyPreservingSimplifier::getResultGeometry() | geos::simplify::TaggedLineStringSimplifier::simplify(geos::simplify::TaggedLineString*) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::hasBadIntersection(geos::simplify::TaggedLineString const*, std::vector<unsigned long, std::allocator<unsigned long> > const&, geos::geom::LineSegment const&) | geos::simplify::TaggedLineStringSimplifier::hasBadInputIntersection(geos::simplify::TaggedLineString const*, std::vector<unsigned long, std::allocator<unsigned long> > const&, geos::geom::LineSegment const&) | geos::simplify::LineSegmentIndex::query(geos::geom::LineSegment const*) const | geos::index::quadtree::NodeBase::visit(geos::geom::Envelope const*, geos::index::ItemVisitor&) | geos::index::quadtree::NodeBase::visit(geos::geom::Envelope const*, geos::index::ItemVisitor&) | geos::index::quadtree::NodeBase::visit(geos::geom::Envelope const*, geos::index::ItemVisitor&) | geos::index::quadtree::NodeBase::visit(geos::geom::Envelope const*, geos::index::ItemVisitor&) | geos::index::quadtree::NodeBase::visit(geos::geom::Envelope const*, geos::index::ItemVisitor&) | geos::index::quadtree::NodeBase::visit(geos::geom::Envelope const*, geos::index::ItemVisitor&) | geos::index::quadtree::NodeBase::visit(geos::geom::Envelope const*, geos::index::ItemVisitor&) | geos::index::quadtree::NodeBase::visit(geos::geom::Envelope const*, geos::index::ItemVisitor&) | geos::index::quadtree::NodeBase::visit(geos::geom::Envelope const*, geos::index::ItemVisitor&) | geos::index::quadtree::NodeBase::visit(geos::geom::Envelope const*, geos::index::ItemVisitor&) | geos::index::quadtree::NodeBase::visit(geos::geom::Envelope const*, geos::index::ItemVisitor&) | geos::index::quadtree::NodeBase::visit(geos::geom::Envelope const*, geos::index::ItemVisitor&) | geos::index::quadtree::NodeBase::visit(geos::geom::Envelope const*, geos::index::ItemVisitor&) | geos::index::quadtree::NodeBase::visitItems(geos::geom::Envelope const*, geos::index::ItemVisitor&) | geos::simplify::LineSegmentVisitor::visitItem(void*) | std::vector<geos::geom::LineSegment*, std::allocator<geos::geom::LineSegment*> >::_M_insert_aux(__gnu_cxx::__normal_iterator<geos::geom::LineSegment**, std::vector<geos::geom::LineSegment*, std::allocator<geos::geom::LineSegment*> > >, geos::geom::LineSegment* const&) | operator new(unsigned long) | malloc start | _start | main | do_all | GEOSTopologyPreserveSimplify | geos::simplify::TopologyPreservingSimplifier::simplify(geos::geom::Geometry const*, double) | geos::simplify::TopologyPreservingSimplifier::getResultGeometry() | geos::simplify::TaggedLineStringSimplifier::simplify(geos::simplify::TaggedLineString*) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::simplifySection(unsigned long, unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::flatten(unsigned long, unsigned long) | geos::simplify::TaggedLineStringSimplifier::remove(geos::simplify::TaggedLineString const*, unsigned long, unsigned long) | geos::simplify::LineSegmentIndex::remove(geos::geom::LineSegment const*) | geos::index::quadtree::Quadtree::remove(geos::geom::Envelope const*, void*) | geos::index::quadtree::Quadtree::ensureExtent(geos::geom::Envelope const*, double) | operator new(unsigned long) | malloc >> modified geostest.c: << #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include "geos_c.h" #define MAXWKTLEN 1047551 void usage(char *me) { fprintf(stderr, "Usage: %s <wktfile>\n", me); exit(1); } void notice(const char *fmt, ...) { va_list ap; fprintf( stdout, "NOTICE: "); va_start (ap, fmt); vfprintf( stdout, fmt, ap); va_end(ap); fprintf( stdout, "\n" ); } void log_and_exit(const char *fmt, ...) { va_list ap; fprintf( stdout, "ERROR: "); va_start (ap, fmt); vfprintf( stdout, fmt, ap); va_end(ap); fprintf( stdout, "\n" ); exit(1); } int do_all(char *inputfile) { GEOSGeometry* g1; GEOSGeometry* g2; static char wkt[MAXWKTLEN]; FILE *input; char *ptr; unsigned char* uptr; size_t size; int i; input = fopen(inputfile, "r"); if ( ! input ) { perror("fopen"); exit(1); } size = fread(wkt, 1, MAXWKTLEN-1, input); fclose(input); if ( ! size ) { perror("fread"); exit(1); } if ( size == MAXWKTLEN-1 ) { perror("WKT input too big!"); exit(1); } wkt[size] = '\0'; /* ensure it is null terminated */ g1 = GEOSGeomFromWKT(wkt); #if 0 /* Simplify */ for (i = 0; i < 100000; i++) { g2 = GEOSSimplify(g1, 0.5); GEOSGeom_destroy(g2); putc('s', stderr); fflush(stderr); } #endif #if 1 /* Topology Preserve Simplify */ for (i = 0; i < 100000; i++) { g2 = GEOSTopologyPreserveSimplify(g1, 0.5); GEOSGeom_destroy(g2); putc('t', stderr); fflush(stderr); } #endif GEOSGeom_destroy(g1); getc(stdin); return 0; } int main(int argc, char **argv) { int i, n=1; initGEOS(notice, log_and_exit); printf("GEOS version %s\n", GEOSversion()); if ( argc < 2 ) usage(argv[0]); if ( argc > 2 ) n=atoi(argv[2]); if ( ! n ) n=1; for (i=0; i<n; i++) { do_all(argv[1]); } putc('\n', stderr); finishGEOS(); return EXIT_SUCCESS; } >> _______________________________________________ geos-devel mailing list geos-devel@lists.osgeo.org http://lists.osgeo.org/mailman/listinfo/geos-devel