Complete.Org: Mailing Lists: Archives: freeciv-ai: November 2004:
[freeciv-ai] (PR#10613) create_danger_segment called more than once per

[freeciv-ai] (PR#10613) create_danger_segment called more than once per

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: jdorje@xxxxxxxxxxxxxxxxxxxxx
Subject: [freeciv-ai] (PR#10613) create_danger_segment called more than once per node
From: "Gregory Berkolaiko" <Gregory.Berkolaiko@xxxxxxxxxxxxx>
Date: Mon, 22 Nov 2004 22:11:48 -0800
Reply-to: rt@xxxxxxxxxxx

<URL: >

> [jdorje - Thu Oct 21 17:14:15 2004]:
> In fact this bug is inside PF.  When iterating over a danger map
> sometimes the danger segment for a node will be allocated multiple times.
> I really have no idea what's going on here (though I haven't looked
> closely).  Is there supposed to be one danger segment for each direction
> (currently there is just one per node)?  Or are we erronously
> initializing the danger data for the node more than once?
> This patch "fixes" the problem by freeing the data before allocating it
> a second time.  Replace this check with an assert and you can see the
> bug in action.  The patch fixes the leak without breaking anything...but
> there's a pretty good chance the current behavior is buggy.

Your patch was right.  The fears were unfounded -- it is ok for the
danger_segment to be written multiple times.  It is the danger-PF
analogue of dir_to_here which gets overwritten every now and then when
we find a better route.

Attached patch moves things around a bit, adds an error message (can do
an assert too but it's not a critical mistake) and adds some comments.


Index: common/aicore/path_finding.c
RCS file: /home/freeciv/CVS/freeciv/common/aicore/path_finding.c,v
retrieving revision 1.26
diff -u -r1.26 path_finding.c
--- common/aicore/path_finding.c        22 Nov 2004 19:14:41 -0000      1.26
+++ common/aicore/path_finding.c        23 Nov 2004 06:04:44 -0000
@@ -771,11 +771,7 @@
   /* Allocating memory */
   if (d_node1->danger_segment) {
-    /* FIXME: it is probably a major bug that create_danger_segment gets
-     * called more than once per node.  Here we prevent a memory leak when
-     * it happens, but who knows what other problems it could cause?  See
-     * PR#10613. */
-    free(d_node1->danger_segment);
+    freelog(LOG_ERROR, "Possible memory leak in create_danger_segment");
   d_node1->danger_segment = fc_malloc(length * sizeof(struct pf_danger_pos));
@@ -831,14 +827,16 @@
   return cost;
   Primary method for iterative path-finding in presence of danger
   1. Whenever the path-finding stumbles upon a dangerous 
   location, it goes into a sub-Dijkstra which processes _only_ 
   dangerous locations, by means of a separate queue.  When this
   sub-Dijkstra reaches a safe location, it records the segment of
-  the path going across the dangerous terrain.
+  the path going across the dangerous terrain.  Hence danger_segment is an
+  extended (and reversed) version of the dir_to_here field.  It can be 
+  re-recorded multiple times as we find shorter and shorter routes.
   2. Waiting is realised by inserting the (safe) tile back into 
   the queue with a lower priority P.  This tile might pop back 
   sooner than P, because there might be several copies of it in 
@@ -856,7 +854,7 @@
   is one.  To gurantee the best (in terms of total_CC) safe segments 
   across danger, supply get_EC which returns small extra on 
   dangerous tiles.
 static bool danger_iterate_map(struct pf_map *pf_map)
   mapindex_t index;
@@ -941,16 +939,16 @@
          node1->cost = cost;
          node1->dir_to_here = dir;
           d_node1->step = loc_step + 1;
+          /* Clear the previously recorded path back */
+          if (d_node1->danger_segment) {
+            free(d_node1->danger_segment);
+            d_node1->danger_segment = NULL;
+          }
          if (d_node->is_dangerous) {
            /* Transition from red to blue, need to record the path back */
            create_danger_segment(pf_map, dir, d_node1, 
          } else {
-           /* Clear the path back */
-           if (d_node1->danger_segment) {
-             free(d_node1->danger_segment);
-             d_node1->danger_segment = NULL;
-           }
             /* We don't consider waiting to get to a safe tile as 
              * "real" waiting */
            d_node1->waited = FALSE;

[Prev in Thread] Current Thread [Next in Thread]
  • [freeciv-ai] (PR#10613) create_danger_segment called more than once per node, Gregory Berkolaiko <=