J'essaie de trouver comment stocker puis imprimer la pile actuelle dans mes applications C++ sur Mac OS X. Le problème principal semble être que dladdr renvoie le bon symbole quand donné une adresse dans l'exécutable principal. Je soupçonne que la question est en fait une option de compilation, mais je ne suis pas sûr.Obtention de la trace de la pile actuelle sous Mac OS X
J'ai essayé le code de traçage de Darwin/Leopard mais il appelle dladdr et a le même problème que mon propre code appelant dladdr.
Original post: Actuellement, je suis capturer la pile avec ce code:
int BackTrace(Addr *buffer, int max_frames)
{
void **frame = (void **)__builtin_frame_address(0);
void **bp = (void **)(*frame);
void *ip = frame[1];
int i;
for (i = 0; bp && ip && i < max_frames; i++)
{
*(buffer++) = ip;
ip = bp[1];
bp = (void**)(bp[0]);
}
return i;
}
qui semble bien fonctionner. Ensuite, pour imprimer la pile je regarde en utilisant dladdr comme ceci:
Dl_info dli;
if (dladdr(Ip, &dli))
{
ptrdiff_t offset;
int c = 0;
if (dli.dli_fname && dli.dli_fbase)
{
offset = (ptrdiff_t)Ip - (ptrdiff_t)dli.dli_fbase;
c = snprintf(buf, buflen, "%s+0x%x", dli.dli_fname, offset);
}
if (dli.dli_sname && dli.dli_saddr)
{
offset = (ptrdiff_t)Ip - (ptrdiff_t)dli.dli_saddr;
c += snprintf(buf+c, buflen-c, "(%s+0x%x)", dli.dli_sname, offset);
}
if (c > 0)
snprintf(buf+c, buflen-c, " [%p]", Ip);
Ce qui fonctionne presque, une sortie par exemple:
/Users/matthew/Library/Frameworks/Lgi.framework/Versions/A/Lgi+0x2473d(LgiStackTrace+0x5d) [0x102c73d]
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x2a006(tart+0x28e72) [0x2b006]
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x2f438(tart+0x2e2a4) [0x30438]
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x35e9c(tart+0x34d08) [0x36e9c]
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x1296(tart+0x102) [0x2296]
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x11bd(tart+0x29) [0x21bd]
Il devient juste le nom de la méthode de l'objet partagé, mais pas pour l'application principale. Ceux-ci se contentent de "piquer" (ou de "commencer" moins le premier caractère).
Idéalement, j'aimerais connaître les numéros de ligne ainsi que le nom de la méthode à ce moment-là. Mais je vais me contenter du bon nom de fonction/méthode pour les débutants. Peut-être tirer pour les numéros de ligne après cela, sur Linux, j'entends que vous devez écrire votre propre analyseur pour un bloc ELF privé qui a son propre jeu d'instructions. Ça fait peur.
De toute façon, quelqu'un peut-il trier ce code afin qu'il obtienne le nom de la méthode?
Je cible actuellement les versions actuelles et précédentes, à savoir Leopard et Tiger. Aussi j'ai actuellement Tiger sur mon Macbook. Donc, jusqu'à ce que Snow Leopard sorte, mon code devra compiler/fonctionner sur Tiger. – user33847
Eh bien, le code source de ces fonctions est opensource, donc vous pouvez probablement inclure l'implémentation dans votre application. Je suis en train d'éditer ma réponse avec les informations pertinentes. –
J'ai jeté un oeil sur le code que vous avez posté des liens et il utilise finalement dladdr exactement le même que mon code. Ce qui donne les mêmes mauvais résultats, en ce que tout ce qui se trouve dans mon exécutable (c'est-à-dire, pas un objet partagé) porte le symbole "tarte". – user33847