[GRASS5] [bug #869] (grass) Possible memory leak in src/libes/vect32/Vlib/get_area.c:Vect_get_area_points()

this bug's URL: http://intevation.de/rt/webrt?serial_num=869
-------------------------------------------------------------------------

Subject: Possible memory leak in src/libes/vect32/Vlib/get_area.c:Vect_get_area_points()

Platform: Linux/Intel
Linux distro: Conectiva
linux cpu: Intel (i486, i586, pentium ...)
Xwindows version: Xfree 4.0.x
Xwindows manager: WindowMaker
TclTk version: tcl/tk 8.3
grass downloaded at: Hannover site
grass binary for platform: I compiled the sources myself
grass sources source: yes, I am using the latest GRASS from CVS
c compiler name: gcc

  I am using this (unfinished) code to draw vectors, from a "backend"
program that talks to a "frontend" gui program.

--
typedef struct _GrassVectInfo {
    char *name; /* vector name */
    char *line, *fill; /* last value used */
    char *mapset;
    int linecolor, fillcolor; /* cached result */
    struct Map_info map;
    struct line_pnts *points;
} GrassVectInfo;

GrassVectInfo *GrassGetVector(char*);
void GrassDisplayVector(GrassVectInfo*, char*, char*);

static GrassVectInfo **vect_info;
static int num_vect_info;

GrassVectInfo *
GrassGetVector(char *name)
{
    int i;
    char *mapset;
    GrassVectInfo *info;

    /* check if vector not already loaded */
    for (i = 0; i < num_vect_info; i++)
  if (strcmp(name, vect_info[i]->name) == 0)
      return (vect_info[i]);

    if ((mapset = G_find_file2("dig", name, "")) == NULL)
  return (NULL);

    if ((info = calloc(1, sizeof(GrassVectInfo))) == NULL)
  return (NULL);

    if (Vect_open_old(&info->map, name, mapset) < 2) {
  free(info);
  return (NULL);
    }

    info->name = strdup(name);
    info->mapset = strdup(mapset);

    /* XXX Vect_new_line_struct() vai chamar G_fatal_error
     * se não houver memória suficiente */
    info->points = Vect_new_line_struct();

    vect_info = realloc(vect_info, sizeof(GrassVectInfo*) *
      (num_vect_info + 1));
    vect_info[num_vect_info++] = info;

    return (info);
}

void
GrassDisplayVector(GrassVectInfo *info, char *line, char *fill)
{
    int i;
    double *x, *y;
    struct Cell_head window;

    Vect_rewind(&info->map);

    R_open_driver();
    D_setup(0);

    G_get_set_window(&window);

    G_setup_plot(D_get_d_north(), D_get_d_south(),
     D_get_d_west(), D_get_d_east(),
     D_move_abs, D_cont_abs);

    Vect_set_constraint_region(&info->map, window.north, window.south,
             window.east, window.west);

    /* preenche polígonos */
    if (info->fill == NULL || strcmp(info->fill, fill)) {
  free(info->fill);
  info->fill = strdup(fill);
  info->fillcolor = D_translate_color(info->fill);
    }

    if (strcmp(info->fill, "none") != 0) {
  int npoints;
  int line, nlines;
  double N, S, E, W;

  R_standard_color(info->fillcolor);

  nlines = V2_num_areas(&info->map);
  for (line = 1; line <= nlines; line++) {
      if (Vect_get_area_points(&info->map, line, info->points) < 0)
    break;

      V2_get_area_bbox(&info->map, line, &N, &S, &E, &W);
      if (S > window.north || N < window.south ||
    W > window.east || E < window.west)
    continue;

      G_plot_polygon(info->points->x, info->points->y,
         info->points->n_points);
  }

  Vect_rewind(&info->map);
    }

    /* desenha contorno */
    if (info->line == NULL || strcmp(info->line, line)) {
  free(info->line);
  info->line = strdup(line);
  info->linecolor = D_translate_color(info->line);
    }
    R_standard_color(info->linecolor);

    for (;:wink: {
        if (Vect_read_next_line(&info->map, info->points) < 0)
      break;
  x = info->points->x;
  y = info->points->y;
  for (i = 1; i < info->points->n_points; i++, x++, y++)
      G_plot_line(x[0], y[0], x[1], y[1]);
    }

    R_close_driver();
}
--

  The problem is the code

--
  BPoints->n_points = 0;
  BPoints->alloc_points = 0;
  Area = &(Map->Area[area]) ;
--

in Vect_get_area_points(), if I replace it by

--
  G_free(BPoints->x);
  G_free(BPoints->y);
  BPoints->n_points = 0;
  BPoints->alloc_points = 0;
  Area = &(Map->Area[area]) ;
--

the problem seens to go away.

  I am testing it with maps with more than 64k polygons, and with the patch,
memory usage seens constant, when running the sample GrassDisplayVector
function several times. I believe a better aproach should be done to fix
the problem, as it is not really required to free the memory to just
reallocate it in the code below, but I preferred to not change the logic
of the code in the sample fix.

Paulo

-------------------------------------------- Managed by Request Tracker

On Tue, 11 Dec 2001 22:57:23 +0100 (CET), Request Tracker <grass-bugs@intevation.de> wrote:

this bug's URL: http://intevation.de/rt/webrt?serial_num=869
-------------------------------------------------------------------------

Subject: Possible memory leak in src/libes/vect32/Vlib/get_area.c:Vect_get_area_points()

[snip]

  The problem is the code

--
  BPoints->n_points = 0;
  BPoints->alloc_points = 0;
  Area = &(Map->Area[area]) ;
--

in Vect_get_area_points(), if I replace it by

--
  G_free(BPoints->x);
  G_free(BPoints->y);
  BPoints->n_points = 0;
  BPoints->alloc_points = 0;
  Area = &(Map->Area[area]) ;
--

the problem seens to go away.

  I am testing it with maps with more than 64k polygons, and with the patch,
memory usage seens constant, when running the sample GrassDisplayVector
function several times. I believe a better aproach should be done to fix
the problem, as it is not really required to free the memory to just
reallocate it in the code below, but I preferred to not change the logic
of the code in the sample fix.

Yes, I think your correct about the memory leak. The code should not assume
the line_struct is empty when it gets it. I think you're also correct that
the right way to handle this is to use realloc() (if necessary) rather than
using free, as it could improve performance a little (especially when no
new memory is needed).

--
Eric G. Miller <egm2@jps.net>

On Tue, 11 Dec 2001 18:06:52 -0800, "Eric G. Miller" <egm2@jps.net> wrote:

On Tue, 11 Dec 2001 22:57:23 +0100 (CET), Request Tracker <grass-bugs@intevation.de> wrote:

> this bug's URL: http://intevation.de/rt/webrt?serial_num=869
> -------------------------------------------------------------------------
>
> Subject: Possible memory leak in src/libes/vect32/Vlib/get_area.c:Vect_get_area_points()
[snip]
>
> The problem is the code
>
> --
> BPoints->n_points = 0;
> BPoints->alloc_points = 0;
> Area = &(Map->Area[area]) ;
> --
>
> in Vect_get_area_points(), if I replace it by
>
> --
> G_free(BPoints->x);
> G_free(BPoints->y);
> BPoints->n_points = 0;
> BPoints->alloc_points = 0;
> Area = &(Map->Area[area]) ;
> --

I committed a fix which just comments out the zeroing of BPoints->alloc_points.
The dig_alloc routines should then properly handle memory without there
being leakage. There is other leakage still, but not so egregious...

--
Eric G. Miller <egm2@jps.net>