Notes d'étude de démarrage RT-Thread - Affirmation de débogage et de dépannage du logiciel Keil MDK

Contexte

  • Débogage logiciel, peu de code est écrit, sans débogage, vous pouvez savoir où se trouve le problème, en particulier l'assertion RT_ASSERT.
  • Il y a plus de fonctions. Après l'apparition de l'assertion RT_ASSERT, il est difficile de comprendre immédiatement ce qui n'a pas fonctionné, comme l'assertion rt_free. D'où l'appel à rt_free l'a-t-il causé?
  • Comment utiliser Keil MDK5 Debug pour affirmer rapidement la vraie position de l'assertion et déboguer le logiciel?

étude de cas

  • J'ai écrit un programme BUG avant pour tester l'utilisation de la boîte aux lettres RT-Thread, et je dois maintenant affirmer: rt_free, car l'application et la libération de la mémoire dynamique sont utilisées.
  • Tout d'abord, nous devons localiser le problème, nous ne pouvons pas dire qu'il y a un problème avec la fonction rt-thread rt_free! ! Cela devrait être causé par une utilisation incorrecte.

2021-02-19_180711.png

2021-02-20_104007.png

2021-02-20_104124.png

  • Keil MDK5 est en mode Débogage, vous pouvez trouver la relation d'appel des fonctions, telles que l'appelant, dans la fenêtre de débogage [Call Stack], fenêtre de pile d'appels.

2021-02-20_104330.png

2021-02-20_105218.png

2021-02-20_105346.png

2021-02-20_105450.png

2021-02-20_105546.png

2021-02-20_105744.png

  • Grâce à [suivez la vigne], trouvez la véritable fonction d'appel: l'emplacement du problème! !

2021-02-20_105847.png

 

Dépannage

  • Le problème avec cette routine est causé par le pointeur nul rt_free, il doit donc être causé par l'opération de paire incorrecte d'application et de libération de mémoire.
  • Comme je n’ai pas trouvé le problème tout de suite, j’ai défini un point d’arrêt à l’emplacement du code du problème et j’ai constaté qu’il y avait un problème avec le pointeur rt_free lors de la deuxième exécution, ou qu’il s’agissait d’un pointeur sauvage.
  • Quote: extern void list_mem (void); Ajouter pour imprimer et constater que la mémoire devient de plus en plus! ! (Beaucoup de versions de rt_free !!)
  • La partie du code qui a mal tourné est la suivante:
struct mb_msg
{
    rt_uint8_t *data_ptr;
    rt_uint32_t data_size;
};


static void thread1_entry(void *param)
{
    struct mb_msg *msg_recv_ptr1;
    struct mb_msg *msg_send_ptr1;
    char sbuf[6] = {'T', 'a', 's', 'k', '1', '.'};
    msg_send_ptr1 = (struct mb_msg *)rt_malloc(sizeof(struct mb_msg)); /* !!!! 申请内存的位置放错了!!!*/

    while(1)
    {
        if (rt_mb_recv(&t1_mb, (rt_ubase_t *)&msg_recv_ptr1, RT_WAITING_FOREVER) == RT_EOK)
        {
            rt_kprintf("thread 1:[recv=%s], print 1.\n", msg_recv_ptr1->data_ptr);
            rt_thread_mdelay(10);
            rt_free(msg_recv_ptr1->data_ptr);
            rt_free(msg_recv_ptr1);
            rt_thread_mdelay(500);
            msg_send_ptr1->data_size = sizeof(sbuf);
            msg_send_ptr1->data_ptr = (rt_uint8_t *)rt_malloc(msg_send_ptr1->data_size);
            rt_memcpy(msg_send_ptr1->data_ptr, sbuf, sizeof(sbuf));
            rt_kprintf("thread 1:[send=%s]\n", msg_send_ptr1->data_ptr);
            rt_mb_send(&t2_mb, (rt_uint32_t)msg_send_ptr1);
        }
    }
}
  • Il s'est avéré qu'un endroit où la mémoire a été demandée était mal placé, ce qui fait que cette fonction ne s'applique qu'une seule fois pour la mémoire lors de l'initialisation. Lorsqu'elle est utilisée, c'est un pointeur sauvage.
  • Solution: placez le morceau de code qui s'applique pour la mémoire dans la boucle while (1) et appliquez pour la mémoire pour chaque opération! !
static void thread1_entry(void *param)
{
    struct mb_msg *msg_recv_ptr1;
    struct mb_msg *msg_send_ptr1;
    char sbuf[6] = {'T', 'a', 's', 'k', '1', '.'};

    while(1)
    {
        if (rt_mb_recv(&t1_mb, (rt_ubase_t *)&msg_recv_ptr1, RT_WAITING_FOREVER) == RT_EOK)
        {
            rt_kprintf("thread 1:[recv=%s], print 1.\n", msg_recv_ptr1->data_ptr);
            rt_thread_mdelay(10);
            rt_free(msg_recv_ptr1->data_ptr);
            list_mem();
            rt_free(msg_recv_ptr1);
            list_mem();
            rt_thread_mdelay(500);
            msg_send_ptr1 = (struct mb_msg *)rt_malloc(sizeof(struct mb_msg));
            msg_send_ptr1->data_size = sizeof(sbuf);
            msg_send_ptr1->data_ptr = (rt_uint8_t *)rt_malloc(msg_send_ptr1->data_size);
            rt_memcpy(msg_send_ptr1->data_ptr, sbuf, sizeof(sbuf));
            rt_kprintf("thread 1:[send=%s]\n", msg_send_ptr1->data_ptr);
            rt_mb_send(&t2_mb, (rt_uint32_t)msg_send_ptr1);
        }
    }
}

Pour résumer

  • RT_ASSERT est encore relativement facile à utiliser, faites attention aux points d'arrêt corrects, au débogage, très efficace.
  • Résumez plus de méthodes de débogage pour résoudre les problèmes réels.

Je suppose que tu aimes

Origine blog.csdn.net/tcjy1000/article/details/113915080
conseillé
Classement