Existe-t-il un moyen moins coûteux de trouver la profondeur de la stack d’appels que l’utilisation de backtrace ()?

Mon code de journalisation utilise la valeur de retour de backtrace () pour déterminer la profondeur actuelle de la stack (à des fins d’impression intéressantes), mais le profilage indique qu’il s’agit d’un appel assez coûteux.

Je ne suppose pas qu’il existe un moyen moins coûteux de faire cela? Notez que je ne me soucie pas des adresses de frameworks, mais du nombre d’adresses.

edit: Ces fonctions de journalisation sont utilisées dans une grande base de code. Par conséquent, le suivi manuel de la profondeur de la stack n’est pas vraiment une option.

    Parcourir la stack vous-même est assez rapide – la lenteur de backtrace() provient en grande partie de la recherche des noms de symboles. Sur x86, vous pouvez effectuer les opérations suivantes:

     inline uint32_t get_ebp(void) { __asm__ __volatile__("mov %%ebp, %%eax"); } int get_stack_depth(void) { uint32_t ebp = get_ebp(); int stack_depth = 0; while(ebp != 0) { ebp = *(uint32_t *)ebp; stack_depth++; } return stack_depth; } 

    Cela permettra de parcourir la chaîne de pointeurs ebp . Gardez à l’esprit que c’est extrêmement non-portable. Notez également que cela ne comptera pas les fonctions qui ont été en ligne ou optimisées au dernier appel (bien sûr, backtrace() a le même problème).

    Un autre problème important est la condition de terminaison – une fois que vous faites une trace dans main() , il n’ya souvent aucune garantie quant à ce que vous trouverez dans la stack. Donc, si libc ne met pas de pointeur de cadre nul, vous aurez très probablement segfault. Vous pouvez obtenir la valeur de terminaison en la regardant au tout début de main() .

    Si vos fonctions d’impression esthétique sont raisonnablement contenues, transmettez le retrait (ou la taille du retrait) en tant que paramètre et augmentez-le simplement lorsque vous appelez d’autres fonctions d’affichage.

    Ne pouvez-vous pas simplement emporter avec vous une variable TLS appelée “profondeur” et l’incrémenter / la décrémenter à chaque fonction? Bien que vous puissiez écrire votre propre code pour parcourir la stack plus rapidement, il sera quand même plus lent que de simplement transporter la variable avec vous.

    Pour les architectures de arm:

     register unsigned long *rfp asm("fp"); unsigned long *fp = rfp; unsigned long depth = 0; while(fp) { fp = (unsigned long *)(*(fp -3)); depth++; } return depth;