Angenommen ich eine rekursive Funktion haben, die eine Graphenstruktur manipuliert:Wie kann ich den Stapelrahmen einer tief rekursiven Funktion in C reduzieren?
typedef struct Node {
Data data;
size_t visited;
size_t num_neighbors;
struct Node *neighbors[];
} Node;
void doSomethingWithNode(Node *node)
{
if ((!node) || node->visited)
return;
node->visited = 1;
/* Do something with node->data */
size_t /* some local variables */;
size_t i;
for (i = 0; i < node->num_neighbors; i++)
{
/* Do some calculations with the local variables */
if (/* something */)
doSomethingWithNode(node->neighbors[i]);
}
}
Aufgrund der lokalen Variablen I in der Schleife zu verwenden, erzeugt der Compiler (gcc
) einen über-I-wäre-like Stapelrahmen für diese Funktion (eine gute Anzahl von pushq
und popq
Anweisungen sogar mit -O3
), was ein Problem ist, da es tief rekursiv ist. Da es egal ist, in welcher Reihenfolge ich die Knoten besuche, könnte ich diesen Code umgestalten, um einen Stapel von Node
Zeigern zu verwenden, wodurch der Aufwand auf einen Zeiger pro Iteration reduziert wird.
- Gibt es irgendwelche Hinweise, die ich dem Compiler geben kann (
gcc
), um dieses Problem zu beheben? - Wenn nicht, ist es möglich, den Aufrufstapel selbst für meinen Stapel von Zeigern zu verwenden, ohne auf die Assembly zuzugreifen?
Alle rekursiven Code kann auch als nicht-rekursive ausgedrückt werden unter Verwendung von Schleifen. Sie können die Stack-Größe auch erhöhen, wenn Sie eine Verbindung herstellen (z. B. die Option '-z Stack-Größe' [Linker-Option] (https://sourceware.org/binutils/docs/ld/Options.html#Options)), wenn die Standardgröße 8 MB beträgt (auf Linux) ist nicht genug. Obwohl ich die Notwendigkeit nicht wirklich sehe, da die Anzahl der lokalen Variablen relativ klein ist (abhängig von "einigen lokalen Variablen" natürlich) und ohne Arrays. Und die lokalen Variablen werden nicht wirklich mit "Push" - und "Pop" -Anweisungen gehandhabt, also schaut ihr wirklich auf den richtigen Code? –
Nach einem kurzen Blick in die GCC-Manpage sehe ich eine Option -fconserve-stack. Hast du es versucht? – Marian
@Marian: Danke! Ich werde es versuchen. – Matt