Remove recursion in getclosedlink
The function getclosedlink in report.c uses recursion to find closed links when reporting on disconnections. In very large networks, it’s possible for the recursion to exhaust the memory on the call stack which then causes EPANET to crash. If a loop is used instead of recursion, EPANET will not crash with very large disconnections
This commit is contained in:
50
src/report.c
50
src/report.c
@@ -45,7 +45,7 @@ static void writeenergy(Project *);
|
||||
static int writeresults(Project *);
|
||||
static int disconnected(Project *);
|
||||
static void marknodes(Project *, int, int *, char *);
|
||||
static void getclosedlink(Project *, int, char *);
|
||||
static void getclosedlink(Project *, int, char *, int *);
|
||||
static void writelimits(Project *, int, int);
|
||||
static int checklimits(Report *, double *, int, int);
|
||||
static char *fillstr(char *, char, int);
|
||||
@@ -1287,7 +1287,7 @@ int disconnected(Project *pr)
|
||||
clocktime(rpt->Atime, time->Htime));
|
||||
writeline(pr, pr->Msg);
|
||||
}
|
||||
getclosedlink(pr, j, marked);
|
||||
getclosedlink(pr, j, marked, nodelist);
|
||||
}
|
||||
|
||||
// Free allocated memory
|
||||
@@ -1350,11 +1350,12 @@ void marknodes(Project *pr, int m, int *nodelist, char *marked)
|
||||
}
|
||||
}
|
||||
|
||||
void getclosedlink(Project *pr, int i, char *marked)
|
||||
void getclosedlink(Project *pr, int i, char *marked, int *stack)
|
||||
/*
|
||||
**----------------------------------------------------------------
|
||||
** Input: i = junction index
|
||||
** marked[] = marks nodes already examined
|
||||
** stack[] = stack to hold nodes to examine
|
||||
** Output: None.
|
||||
** Purpose: Determines if a closed link connects to junction i.
|
||||
**----------------------------------------------------------------
|
||||
@@ -1365,20 +1366,41 @@ void getclosedlink(Project *pr, int i, char *marked)
|
||||
int j, k;
|
||||
Padjlist alink;
|
||||
|
||||
int top = 0;
|
||||
|
||||
// Mark the current junction as examined and push onto stack
|
||||
marked[i] = 2;
|
||||
for (alink = net->Adjlist[i]; alink != NULL; alink = alink->next)
|
||||
{
|
||||
k = alink->link;
|
||||
j = alink->node;
|
||||
if (marked[j] == 2) continue;
|
||||
if (marked[j] == 1)
|
||||
{
|
||||
sprintf(pr->Msg, WARN03c, net->Link[k].ID);
|
||||
writeline(pr, pr->Msg);
|
||||
return;
|
||||
stack[top] = i;
|
||||
|
||||
while (top >= 0) {
|
||||
i = stack[top--];
|
||||
alink = net->Adjlist[i];
|
||||
|
||||
// Iterate through each link adjacent to the current node
|
||||
while (alink != NULL) {
|
||||
k = alink->link;
|
||||
j = alink->node;
|
||||
|
||||
// Skip nodes that have already been examined
|
||||
if (marked[j] == 2) {
|
||||
alink = alink->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If a closed link is found, return and display a warning message
|
||||
if (marked[j] == 1) {
|
||||
sprintf(pr->Msg, WARN03c, net->Link[k].ID);
|
||||
writeline(pr, pr->Msg);
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark the node as examined and push it onto the stack
|
||||
marked[j] = 2;
|
||||
stack[++top] = j;
|
||||
alink = alink->next;
|
||||
}
|
||||
else getclosedlink(pr, j, marked);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void writelimits(Project *pr, int j1, int j2)
|
||||
|
||||
Reference in New Issue
Block a user