[GRASS-dev] Re: [GRASS GIS] #837: Memory leaks in r.example

GRASS GIS trac at osgeo.org
Wed Dec 16 11:46:57 EST 2009


#837: Memory leaks in r.example
----------------------+-----------------------------------------------------
  Reporter:  sprice   |       Owner:  grass-dev at lists.osgeo.org
      Type:  defect   |      Status:  reopened                 
  Priority:  normal   |   Milestone:  6.4.0                    
 Component:  default  |     Version:  svn-releasebranch64      
Resolution:           |    Keywords:                           
  Platform:  MacOSX   |         Cpu:  OSX/Intel                
----------------------+-----------------------------------------------------
Comment (by glynn):

 Replying to [comment:3 sprice]:
 > Judging by the 1616 leaked nodes in get_map_row() this is on a per row
 basis. But I've never heard of a well written program containing leaks
 anyway.

 No program leaks, insofar as all of its memory is returned to the system
 upon termination. It's just a question of how much memory it uses while
 it's running. Most programs could have their memory consumption reduced;
 it's a question of whether it's worth the effort and (more importantly)
 added complexity.

 > Here's your fix for the first leak:
 > Change line 58 in lib/gis/gisinit.c from "G_location_path();" to
 "G_free(G_location_path());"

 This is harmless (it's a fixed amount of memory for the lifetime of the
 process), but it's also trivial to fix.

 > The second leak:
 > Add "G_free(dummy);" at line 1003 in file lib/gis/get_row.c

 This is a '''real''' leak, but I'm not sure that it can be fixed this way,
 as the return value from G_find_* may not be owned by the caller. The
 return value may be a mapset from the current mapset list, in which case
 freeing it will break stuff.

 Historically, the view has been that memory consumed by G_find_* or
 G_open_* isn't an issue; it just means that a process consumes a certain
 amount of memory per map. But the null value handling was hacked on later;
 the fact that it opens and closes the null value bitmap every few rows was
 always known to be inefficient, but I don't think anyone spotted the leak
 before.

 Possible solutions:

 1. Change the null bitmap handling to keep the file open.

 The reason why this wasn't done originally is that it doubles the number
 of open files, which can cause e.g. r.series to run into OS limits on the
 number of open files. It also doubles the number of required fileinfo
 slots, but this is less of a problem now that the fileinfo array is
 dynamically sized.

 2. Make G_find_* return unique allocations, so that they can be freed.
 This may increase fixed memory consumption slightly for some modules, as
 nothing currently frees the return value. But it will reduce it in the
 long run (and in the short run for raster modules by fixing this leak),
 and the worst case with it fixed will still be a lot better than the
 current worst case.

 3. Make open_null_read free the return value. I '''think''' that it will
 always be unique in this case, as a mapset is always being passed in.
 AFAICT, the return value is only shared if the name is unqualified and the
 mapset is NULL or the empty string, indicating that the map should be
 looked up using the mapset search path. A fully-qualified name or an
 unqualified name with an explicit mapset should always return a unique
 value. But if I've overlooked something, freeing the return value will
 cause no end of problems.

 If this was the only issue, my inclination would be for !#2, as we're
 trying to get 6.4 released. In that context, !#1 is too disruptive and !#3
 is a hack which, if it's wrong, may not get discovered until it's too
 late.

 But ...

 > The third, fourth, & last leaks (in lib/gis/opencell.c) are a bit more
 difficult to take care of all permutations:

 [snip]

 This is a large part of the reason why we just resign ourselves to each
 map requiring a certain amount of memory. And I'd leave it at that, if it
 wasn't for the null bitmap handling calling this function repeatedly.

 This specific fix can't be applied without first making G_find_* always
 return unique allocations.

 The fix would be simpler if G_open_cell_old() called G_fatal_error() on
 errors. This would make life simpler for modules, which currently need to
 check the return value. Off the top of my head, I don't know of a single
 case where the caller actually tries to recover from G_open_cell_old()
 failing. Doing so would also be a benefit to a small number of modules
 which forget to check for errors.

 An intermediate solution would be to free the memory under normal
 circumstances and not bother about the leak if G_open_cell_old() fails.
 It's 99.99% likely that the program is going to terminate immediately in
 that situation.

 > The next leak in lib/gis/gdal.c:

 This isn't a problem. Each map which is opened requires some memory. There
 are all sorts of ways in which that memory consumption could be reduced;
 some of them are worth the effort, some of them aren't. Again, this
 specific fix can't be applied without first making G_find_* always return
 unique allocations. If that is done, this would be worthwhile.

 Right now, the only thing that I'm certain of is that the null bitmap
 handling has to change for 7.0, but it's probably too disruptive for 6.x.

-- 
Ticket URL: <http://trac.osgeo.org/grass/ticket/837#comment:4>
GRASS GIS <http://grass.osgeo.org>


More information about the grass-dev mailing list