[En-Nut-Discussion] net/ipout.c memory leak

Stefan Hax stefan at escherlogic.com
Mon Jun 7 02:07:00 CEST 2010


Sorry, the call to (*nif->if_output)() already frees nb_clone in case of 
error.   Although I have not found my memory leak, NutNetBufFree() does 
not look right when dealing with clones. Here is my suggestion:

extending nb_flags in the structure to be a uint16_t instead of a 
uint8_t then:
#define NBAF_DIE	0x0100

... in /net/netbuf.c:

void NutNetBufFree(NETBUF * nb)
{
     if (nb->nb_flags & NBAF_REFCNT) {                   // referecned 
by something??
         nb->nb_flags |= NBAF_DIE;                       // just mark 
this for death

     } else {                                            // no ref... 
start free'ing what is owned
         if (nb->nb_flags & NBAF_DATALINK) {
             if(nb->nb_ref) {
                 if(nb->nb_ref->nb_dl.vp != nb->nb_dl.vp) { 
  // our's to relese?? then relese it.
                     NutHeapFree(nb->nb_dl.vp);
                 }
             } else {
                 NutHeapFree(nb->nb_dl.vp);
             }
         }

         if (nb->nb_flags & NBAF_NETWORK) {
             if(nb->nb_ref) {
                 if(nb->nb_ref->nb_nw.vp != nb->nb_nw.vp) { 
  // our's to relese?? then relese it.
                     NutHeapFree(nb->nb_nw.vp);
                 }
             } else {
                 NutHeapFree(nb->nb_nw.vp);
             }
         }

         if (nb->nb_flags & NBAF_TRANSPORT) {
             if(nb->nb_ref) {
                 if(nb->nb_ref->nb_tp.vp != nb->nb_tp.vp) { 
  // our's to relese?? then relese it.
                     NutHeapFree(nb->nb_tp.vp);
                 }
             } else {
                 NutHeapFree(nb->nb_tp.vp);
             }
         }

         if (nb->nb_flags & NBAF_APPLICATION) {
             if(nb->nb_ref) {
                 if(nb->nb_ref->nb_ap.vp != nb->nb_ap.vp) { 
  // our,s to relese?? then relese it.
                     NutHeapFree(nb->nb_ap.vp);
                 }
             } else {
                 NutHeapFree(nb->nb_ap.vp);
             }
         }

         if (nb->nb_ref) {
             if(nb->nb_ref->nb_flags & NBAF_REFCNT) {            // dec 
parent count of this ref??
                 nb->nb_ref->nb_flags--;
             }

             if(nb->nb_ref->nb_flags & NBAF_DIE) {               // 
parent marked for death?? then free it..
                 NutNetBufFree(nb->nb_ref);
             }
         }

         NutHeapFree(nb);
     }
}

If what is being freed is the 'parent' and their are still references to 
it then only mark for freeing when all clones have been freed. 
Otherwise, this will just release what bufferes were allocated when the 
clone was created and decrement the reference count in the parent then 
free the clone, and finally, the parent is freed once all references are 
gone.

Stefan.

Stefan Hax wrote:
> noticed a small memory leak in ../net/ipout.c during UDP broadcast failures.
> 
> code is:
> NutIpOutput(..)
> {
> ...
>                 if (nif->if_type == IFT_ETHER)
>                      rc = (*nif->if_output) (dev, ETHERTYPE_IP, ha, 
> nb_clone);
>                  else if (nif->if_type == IFT_PPP)
>                      rc = (*nif->if_output) (dev, PPP_IP, 0, nb_clone);
> 
>                  if (rc == 0) {
>                      NutNetBufFree(nb_clone);
>                  }
> ...
> }
> 
> 
> sugested:
> NutIpOutput(..)
> {
> ...
>                 if (nif->if_type == IFT_ETHER)
>                      rc = (*nif->if_output) (dev, ETHERTYPE_IP, ha, 
> nb_clone);
>                  else if (nif->if_type == IFT_PPP)
>                      rc = (*nif->if_output) (dev, PPP_IP, 0, nb_clone);
> 
>                  if(nb_clone) {          /* <-- might be a better choice */
>                      NutNetBufFree(nb_clone);
>                  }
> ...
> }
> 
> 
> Regards, Stefan.
> _______________________________________________
> http://lists.egnite.de/mailman/listinfo/en-nut-discussion
> 



More information about the En-Nut-Discussion mailing list