2012-06-18 4 views
8

मुक्त नहीं कर रहा है मैं lwip नामक एक टीसीपी/आईपी स्टैक का उपयोग कर रहा हूं। मैंने डेटा पैकेट भेजने के लिए नीचे एक फ़ंक्शन लागू किया है, जो डेटा पैकेट प्राप्त करने वाले समान कॉलबैक फ़ंक्शन से प्रेरित है।लाइटवॉइट आईपी: बफर

हर बार एक पैकेट प्राप्त होता है, मैं pbuf_alloc फ़ंक्शन का उपयोग करके एक बफर बना देता हूं। फिर, मैं udp_sendto का उपयोग कर पैकेट भेजता हूं। अंत में, मैं pbuf_free का उपयोग कर बफर को मुक्त करता हूं। (नीचे दिए गए कोड को देखें।)

किसी कारण से, pbuf_free बफर को मुक्त नहीं कर रहा है। (मैं n पैकेट, जहां n पूल आकार है के बाद एक बफर अतिप्रवाह मिलता है।) The lwip wiki चेतावनी दी है कि:

नेटवर्क चालक भी कल्पना नहीं कर सकते हैं कि pbuf स्मृति वास्तव में मुक्त हो जाता है जब यह pbuf_free कहता है।

मैं अपने बफर को मुक्त करने के लिए pbuf_free को कैसे मजबूर कर सकता हूं? बफर ओवरफ्लो से कैसे बचा जाता है?

static struct pbuf *pkt_buf = NULL; 

if(pkt_buf == NULL) 
    pkt_buf = pbuf_alloc(PBUF_TRANSPORT, bytesToSend, PBUF_POOL); 
if(pkt_buf == NULL) 
{ 
    print("(TFTP) Buffer overflow!\r\n"); 
} 

अपने परिदृश्य हैं:

(। मेरे नीचे कार्यान्वयन)

static err_t IAP_tftp_send_data_packet(struct udp_pcb *upcb, struct ip_addr *to, int to_port, int block) 
{ 
    err_t err; 
    struct pbuf *pkt_buf; 
    char packet[TFTP_DATA_PKT_LEN_MAX]; 
    int bytesRead; 
    int bytesToSend; 

    /* Specify that we are sending data. */ 
    IAP_tftp_set_opcode(packet, TFTP_DATA); 

    /* Specify the block number that we are sending. */ 
    IAP_tftp_set_block(packet, block); 

    bytesRead = IAP_tftp_set_data(packet, block); 

    if(bytesRead != 0) { 
    bytesToSend = TFTP_DATA_PKT_LEN_MAX - (512 - bytesRead + 1); 
    } else { 
    bytesToSend = TFTP_DATA_PKT_LEN_MAX - 512; 
    } 

    pkt_buf = pbuf_alloc(PBUF_TRANSPORT, bytesToSend, PBUF_POOL); 

    if (!pkt_buf) 
    { 
    print("(TFTP) Buffer overflow!\r\n"); 
    } 

    /* Copy the file data onto pkt_buf. */ 
    memcpy(pkt_buf->payload, packet, bytesToSend); 

    err = udp_sendto(upcb, pkt_buf, to, to_port); 

    /* free the buffer pbuf */ 
    printf("%d\n\r", pbuf_free(pkt_buf)); 

    return err; 
} 
+0

क्या आपने बफर को संदर्भ गणना की जांच की? मुझे डर है कि अगर संदर्भ संख्या 1 है। – Fred

+0

संभवतः 'udp_sendto' एक संदर्भ लेता है और इसे अतुल्यकालिक रूप से रिलीज़ करता है (टाइमर में)। शायद आपको इसे थोड़ी देर देने की ज़रूरत है? – ugoren

+0

@ugoren: मैंने बफर ओवरफ़्लो होने पर प्रतीक्षा करने का प्रयास किया है, लेकिन बफर ओवरफ़्लो बनी हुई है। – Randomblue

उत्तर

7

आप एलडब्ल्यूआईपी का किस संस्करण का उपयोग कर रहे हैं? विभिन्न संस्करणों के आधार पर उत्तर बहुत भिन्न होते हैं।

ppuf_alloc() के अंदर बुलाया गया memp_malloc() आवंटन फ़ंक्शन विफल हो गया है या pbufs चेनिंग विफल हो गई है। इसलिए, यह शून्य लौटाता है।

pbuf_alloc() भी पास वापस आ जाएगा, यदि पास किए गए तर्कों में भी शून्य शामिल है। (पूर्ण तर्क जांच के कारण)।

नए संस्करणों में, क्या आप दिखा सकते हैं कि MEMP_OVERFLOW_CHECK मैक्रो में क्या मूल्य है? एलडब्ल्यूआईपी एक अलग व्यवहार दिखाता है जब मैक्रो वैल्यू> = 2.

और यदि आप बहु-थ्रेडिंग का उपयोग कर रहे हैं, तो एक अन्य कारण हो सकता है, pbuf_alloc() विफल होने के अंदर लॉकिंग तंत्र, इसे वापस लौटने का कारण बन सकता है।

कुछ संस्करणों की आवश्यकता है कि आप pbuf_inoc() को कॉल करने से पहले pbuf_init() को कॉल करें।

आप इस कोशिश कर सकते हैं:

pkt_buf = NULL;//Use NULL, just incase the NULL is not 0 as per your compiler. 
pkt_buf = pbuf_alloc(PBUF_TRANSPORT, bytesToSend, PBUF_REF); 
if(pkt_buf == NULL) 
{ 
    printf("pbuf_alloc failed.\n"); 
} 
else 
{ 
    /* Do something with the allocated pbufs and free it. */ 
} 

PBUF_REF pbuf के लिए कोई बफर स्मृति आवंटित करेगा। पीबीएफएफ को केवल एक धागे में इस्तेमाल किया जाना चाहिए और यदि पीबीएफ कतारबद्ध हो जाता है, तो बफर की प्रतिलिपि बनाने के लिए pbuf_take को बुलाया जाना चाहिए।

आप पीबीयूएफ_आरएएम भी कोशिश कर सकते हैं जो रैम में बफर आवंटित करेगा।

अधिक जानकारी के लिए, आप एलवीआईपी के संस्करण की स्रोत फ़ाइलों को भी ब्राउज़ कर सकते हैं, जिसका आप उपयोग कर रहे हैं।

+0

मुझे बताएं कि क्या यह उत्तर अभी भी आपके प्रश्न का उत्तर नहीं दे रहा है। – askmish

+0

मैंने आपको बक्षीस दिया क्योंकि आपका जवाब सबसे आशाजनक है। मुझे आपको और विवरण पूछना पड़ सकता है क्योंकि मेरे पास जांच करने का समय है। धन्यवाद। – Randomblue

+0

यदि आप आरामदायक हैं और पर्याप्त समय है, तो मैं आपको विकी के बजाए अपने संस्करण के स्रोत कोड से गुजरने का सुझाव दूंगा। विकी खराब रखरखाव है। – askmish

6

सबसे आसान समाधान बफर static, यानी प्रत्येक कॉल के लिए एक ही बफर फिर से का उपयोग करने के लिए हो रहा है ड्राइवर को अनलोड/पुनः लोड करना शामिल है, यह स्मृति को रिसाव करेगा। इसे ठीक करने के लिए, IAP_tftp_send_data_packet() फ़ंक्शन के बाहर बफर स्थिर बनाएं, और ड्राइवर को अनलोड होने पर pbuf_free() पर कॉल करें (मान लें कि lwip आपको बताता है)।

+0

हम, काम नहीं करता है। अच्छा विचार, यद्यपि। – Randomblue

0

बस एक गुजरने वाला विचार, संभवतः पूरी तरह से बकवास। इस कोड में: - TFTP_DATA_PKT_LEN_MAX

if(bytesRead != 0) { 
    bytesToSend = TFTP_DATA_PKT_LEN_MAX - (512 - bytesRead + 1); 
} else { 
    bytesToSend = TFTP_DATA_PKT_LEN_MAX - 512; 
} 
pkt_buf = pbuf_alloc(PBUF_TRANSPORT, bytesToSend, PBUF_POOL); 

... यह bytesRead मूल्य 513 ग्रहण करने के लिए संभव है?

यदि ऐसा हुआ, तो शून्य बाइट आवंटित करने का अनुरोध विफल नहीं होगा? (यह बफर ओवरफ्लो पर बाइट्स के समर्थन को मुद्रित करके परीक्षण किया जा सकता है, और जांच कर रहा है कि यह nonzero है)।

0

संरचना pbuf स्मृति के निरंतर क्षेत्र का प्रतिनिधित्व नहीं करता है। यह स्मृति स्थानों की एक श्रृंखला है। इस प्रकार यह सामान्य मामले में काम नहीं करेगा:

memcpy(pkt_buf->payload, packet, bytesToSend); 

आपको अपने डेटा को स्कैटर-कॉपी करने की आवश्यकता है। कोड स्निपेट से memcpy() पेलोड बफर को ओवरफ़्लो कर सकता है और सभी प्रकार के साइड इफेक्ट्स का कारण बन सकता है जिसमें पीबीएफ श्रृंखला को साफ करने में असमर्थता शामिल है।