Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

pb fonction récursive avec g++ 3.2

9 réponses
Avatar
pjenty
bonjour,
j'ai un souci avec du code qui s'exécutait bien avec g++ 2.95, mais qui
se plante avec g++ 3.2.
c'est dans le cas d'un appel récursif, lors du 3ième appel récursif.
ça me le fait sur 2 fonctions différentes.
auriez-vous une idée pour résoudre ce problème ?
faut-il une option de compilation précise ?
merci

9 réponses

Avatar
Christophe de Vienne
pjenty wrote:

bonjour,
j'ai un souci avec du code qui s'exécutait bien avec g++ 2.95, mais qui
se plante avec g++ 3.2.
c'est dans le cas d'un appel récursif, lors du 3ième appel récursif.
ça me le fait sur 2 fonctions différentes.
auriez-vous une idée pour résoudre ce problème ?
faut-il une option de compilation précise ?


Sans le code des fonctions en question c'est impossible à dire. Poste un
exemple minimal qui reproduit le problème.

A+

Christophe

--
Christophe de Vienne
Experience is something you don't get until just after you need it.
Oliver's Law.

Avatar
pjenty
voici le code en cause, en espérant que ça te suffira :-)
void processRack(NODE *dawg, register unsigned char *rack, int
bingosOnly, std::string strLewis)
{
unsigned int bingoLength = 0;
unsigned int blanks[MAXWORD];
NODE *edge;
register int i;
register unsigned u;
unsigned int nBlanks = 0;
unsigned int nChars[256];
NODE *stemEdges[MAXWORD];
unsigned char word[MAXWORD];

(void) memset(&nChars[0], 0, sizeof nChars);
while (u = *rack++)
{
bingoLength++;
u == '?' ? nBlanks++ : nChars[u]++;
}

edge = dawg + valRootNode;
i = 0;

while (1)
{
u = chr_(*edge);
if (type == 2) u = u + 'A' - 1;
if (nChars[u])
{
nChars[u]--;
blanks[i] = 0;
goto added_letter;
}
else if (nBlanks)
{
nBlanks--;
blanks[i] = 1;
added_letter:
word[i] = u;
word[i+1] = 0;
if (term_(*edge))
{
if (bingoLength == i+1)
{
if (bingosOnly != 2)
{
f_putWord(word, blanks, i+1);
}
goto unadd;
}
if (bingosOnly == 2 && bingoLength == i+2)
{
gs_strTmp = (char *)word;
gs_strTmp += "?";
processRack(dawg, (unsigned char *)gs_strTmp.c_str(),
2, "strLewis");
}
else if (bingosOnly == 0)
f_putWord(word, blanks, i+1);
}
if (*edge & valNodePointer)
{
stemEdges[i++] = edge;
edge = dawg + pptr_(*edge);
continue;
}
unadd:
blanks[i] ? nBlanks++ : nChars[u]++;
}
up:
while (last_(*edge))
{
if (i-- == 0) return;
blanks[i] ? nBlanks++ : nChars[word[i]]++;
edge = stemEdges[i];
}
edge++;
}
return;
}


Christophe de Vienne a écrit:
pjenty wrote:


bonjour,
j'ai un souci avec du code qui s'exécutait bien avec g++ 2.95, mais qui
se plante avec g++ 3.2.
c'est dans le cas d'un appel récursif, lors du 3ième appel récursif.
ça me le fait sur 2 fonctions différentes.
auriez-vous une idée pour résoudre ce problème ?
faut-il une option de compilation précise ?



Sans le code des fonctions en question c'est impossible à dire. Poste un
exemple minimal qui reproduit le problème.

A+

Christophe




Avatar
Christophe de Vienne
pjenty wrote:
Christophe de Vienne a écrit:
pjenty wrote:


bonjour,
j'ai un souci avec du code qui s'exécutait bien avec g++ 2.95, mais qui
se plante avec g++ 3.2.
c'est dans le cas d'un appel récursif, lors du 3ième appel récursif.
ça me le fait sur 2 fonctions différentes.
auriez-vous une idée pour résoudre ce problème ?
faut-il une option de compilation précise ?



Sans le code des fonctions en question c'est impossible à dire. Poste un
exemple minimal qui reproduit le problème.



voici le code en cause, en espérant que ça te suffira :-)
void processRack(NODE *dawg, register unsigned char *rack, int
bingosOnly, std::string strLewis)



[...]

Le code que tu as posté est du C, non du C++, donc je t'invite à demander de
l'aide sur un forum de C.
(Par ailleurs une indication plus précise sur le moment où ça plante et de
quelle manière ne serait pas superflue.)

A+

Christophe

--
Christophe de Vienne
Experience is something you don't get until just after you need it.
Oliver's Law.



Avatar
pjenty
c'est compilé en c++ car j'utilise la STL et d'autres classes.
ça plante lors de l'appel, car j'ai mis un message (msg1) juste au début
de la fonction et un avant de la lancer (msg2), et bien je n'ai pas msg1
lors du 3ième appel.
ça plante (je suis sous windows) avec le message suivant, mais c'est du
chinois pour moi.
BOGGLEFLTK a causé une défaillance de pile dans le module BOGGLEFLTK.EXE
à 0177:0044b193.
Registres :
EAX04447c CS77 EIP44b193 EFLGS010202
EBX000045 SS7f ESP61e8d4 EBP61e8e8
ECX5d18dc DS7f ESI000004 FS77
EDX8e0d38 ES7f EDI7e2384 GS00
Octets à CS : EIP :
83 09 00 2d 00 10 00 00 eb e9 29 c1 83 09 00 89
État de la pile :
0061e920 004090a0 00000045 00000004 007e2384 006aed88 0040941e 007e1880
008e0bf4 00000002 0061e920 00000000 00000000 00000001 00000005 00000001
Avatar
Christophe de Vienne
pjenty wrote:

c'est compilé en c++ car j'utilise la STL et d'autres classes.
ça plante lors de l'appel, car j'ai mis un message (msg1) juste au début
de la fonction et un avant de la lancer (msg2), et bien je n'ai pas msg1
lors du 3ième appel.
ça plante (je suis sous windows) avec le message suivant, mais c'est du
chinois pour moi.
BOGGLEFLTK a causé une défaillance de pile dans le module BOGGLEFLTK.EXE
à 0177:0044b193.
Registres :
EAX04447c CS77 EIP44b193 EFLGS010202
EBX000045 SS7f ESP61e8d4 EBP61e8e8
ECX5d18dc DS7f ESI000004 FS77
EDX8e0d38 ES7f EDI7e2384 GS00
Octets à CS : EIP :
83 09 00 2d 00 10 00 00 eb e9 29 c1 83 09 00 89
État de la pile :
0061e920 004090a0 00000045 00000004 007e2384 006aed88 0040941e 007e1880
008e0bf4 00000002 0061e920 00000000 00000000 00000001 00000005 00000001


Une de tes instructions doit corrompre la pile.
Essaie peut-être de remplacer le memset par une boucle qui fait des
affectations.
Sinon assures-toi que tu n'accèdes jamais à un indice trop grand dans tes
tableaux qui sont alloués sur la pile (blanks, word etc).

Autre remarque: utiliser des goto est on ne peut plus déconseillé. Les
utiliser montre en générale une erreur de conception.

A+

Christophe

--
Christophe de Vienne
Experience is something you don't get until just after you need it.
Oliver's Law.

Avatar
Christophe de Vienne
Christophe de Vienne wrote:


Sinon assures-toi que tu n'accèdes jamais à un indice trop grand dans tes
tableaux qui sont alloués sur la pile (blanks, word etc).


A ce propos tu devrais utiliser des vector<> au lieu des tableaux. Ça
t'éviterais d'utiliser memset et l'erreur que tu as se serait probablement
traduite par un segfault, plus facile à diagnostiquer.

--
Christophe de Vienne
Experience is something you don't get until just after you need it.
Oliver's Law.

Avatar
Richard Delorme

Le code que tu as posté est du C, non du C++, donc je t'invite à demander
de l'aide sur un forum de C.


Il utilise std::string, c'est donc du C++.
Quoique, avec tous ces gotos, cela ressemble aussi à du fortran.

--
Richard

Avatar
pjenty
le code originel n'est pas de moi, je viens de le "nettoyer" un peu:

void processRack(NODE *dawg, register unsigned /* ajout */ char *rack,
int bingosOnly, std::string strLewis)
{
unsigned int bingoLength = 0;
unsigned int blanks[MAXWORD];
NODE *edge;
register int i;
register unsigned u;
unsigned int nBlanks = 0;
unsigned int nChars[256];
NODE *stemEdges[MAXWORD];
bool addedLetter, unAdd;
unsigned char word[MAXWORD];

if (bingosOnly == 2) affDebug(chaine2("processRack %s %s", rack,
strLewis.c_str()));

for (i = 0; i < 256; i++)
{
nChars[i] = 0;
}

while (u = *rack++)
{
bingoLength++;
if(u == '?')
{
nBlanks++;
}
else
{
nChars[u]++;
}
}

edge = dawg + valRootNode;
i = 0;

while (1)
{
u = chr_(*edge);
addedLetter = false;
unAdd = false;
if (type == 2) u = u + 'A' - 1;
if (nChars[u])
{
nChars[u]--;
blanks[i] = 0;
addedLetter = true;
}
else if (nBlanks)
{
nBlanks--;
blanks[i] = 1;
addedLetter = true;
}

if(addedLetter)
{
word[i] = u;
word[i+1] = 0;
if (term_(*edge))
{
if (bingoLength == i+1)
{
if (bingosOnly != 2)
{
f_putWord(word, blanks, i+1);
}
unAdd = true;
}
if(!unAdd)
{
if (bingosOnly == 2 && bingoLength == i+2)
{
strLewis = strLewis + "|";
strLewis = strLewis + (char *)word;
gs_strTmp = gs_strTmp + (char *)word;
gs_strTmp = gs_strTmp + "?";
if (bingosOnly == 2) affDebug(chaine2("av processRack récursif"));
processRack(dawg, (unsigned char
*)gs_strTmp.c_str(), 2, strLewis);
}
else if (bingosOnly == 0)
{
f_putWord(word, blanks, i+1);
}
}
}
if(!unAdd)
{
if (*edge & valNodePointer)
{
stemEdges[i++] = edge;
edge = dawg + pptr_(*edge);
continue;
}
}
unAdd = true;
if(unAdd)
{
blanks[i] ? nBlanks++ : nChars[u]++;
}
}
while (last_(*edge))
{
if (i-- == 0) return;
blanks[i] ? nBlanks++ : nChars[word[i]]++;
edge = stemEdges[i];
}
edge++;
}
return;
}


et voici le résultat de l'exécution:
lacement par:
processRack(dawg, (unsigned char *) lettres.c_str(), 2,
inputCousin->value());

processRack AVOIR? AVOIR
av processRack récursif
processRack ARROI? AVOIR|ARROI
av processRack récursif
processRack ARROI?AIRER? AVOIR|ARROI|AIRER
av processRack récursif


je n'ai donc même pas le message de début de fonction:
processRack ....

je n'y comprend rien, et aucun souci avec g++ 2.95

quant aux last_, term_, ce sont juste des tests sur des bits
#define last_(var) ((var) & valLast)
#define term_(var) ((var) & valTerm)
#define chr_(var) (((var) >> valVLetter) & valMLetter)
#define pptr_(var) (((var) >> valVNode) & valMNode)
Avatar
pjenty
MAXWORD vaut 256
strLewis est édité dans le fichier trace et n'est pas très long:
AVOIR|ARROI|AIRER lors du dernier affichage
et donc, 6 caractères de plus lors de l'appel qui plante tout.

sur vos conseils, j'ai essayé avec:
std::vector<unsigned int> nChars(256, 0);
std::vector<unsigned int> blanks(256, 0);
std::vector<unsigned long *>stemEdges(256);
et, surprise, ça ne plante plus.
merci pour les explications sur les piles, c'est ce qui à dû résoudre le pb.