2013-03-27 9 views
7

का उदाहरण फेंकने के बाद बुलाया जाता है। मैं एक दोगुनी लिंक्ड लिस्ट क्लास को कार्यान्वित कर रहा हूं जो 'बाल्टी' (नोड्स) को स्टोर करता है, जिनमें प्रत्येक में वर्णों की पूर्वनिर्धारित संख्या होती है। प्रत्येक बाल्टी अगले और पिछली बाल्टी में एक सूचक को स्टोर करती है, और सूची वर्ग (बकेटस्ट्रिंग) सिर बाल्टी में एक सूचक को स्टोर करता है। मैं जी ++ जो त्रुटि फेंकता का उपयोग कर संकलन कर रहा हूँसी ++: 'std :: bad_alloc'

terminate called after throwing an instance of 'std::bad_alloc' 
    what(): std::bad_alloc 
make: *** [run] Aborted (core dumped) 

जब भी मैं कोड चलाने के लिए और सूची में वर्णों की स्ट्रिंग जोड़ने के लिए, विधि है, जो मेरी बाल्टी वर्ग के भीतर निहित है जोड़ने के निम्न का उपयोग कर, और से कहा जाता है जब चाहें वर्ग की अपनी विधियों की सूची बनाएं।

कोड:

std::size_t bucketSizeB; 
int filled; 
char* str; 
Bucket* next; 
Bucket* prev; 

Bucket::Bucket() : bucketSizeB(7), str(new char[7]), next(NULL), prev(NULL), filled(0) 
{} 

Bucket::Bucket(std::size_t bucketSizeB_) : bucketSizeB(bucketSizeB_), str(new char[bucketSizeB]), next(NULL), prev (NULL), filled(0) 
{} 

Bucket::Bucket(const Bucket& rhs) : bucketSizeB(rhs.bucketSizeB), next(rhs.next), prev(rhs.prev), filled(rhs.filled) 
{ 
    for (int i = 0 ; i < (int) bucketSizeB ; i++) 
    { 
     str[i] = rhs.str[i]; 
    } 
} 

void Bucket::add(std::string line) 
{ 

    int diff = bucketSizeB - filled; //if the bucket is already partially filled 


    std::string tmp = line.substr(0, diff); 

    for (std::size_t i = 0 ; i < tmp.length() ; i++) 
    { 

     str[filled] = line[i]; 
     ++filled; 
    } 

    if (line.length() > bucketSizeB) 
    { 

     next = new Bucket(bucketSizeB); 

     next->prev = this; 
     next->add(line.substr(diff, line.length()-diff)); 
    } 
} 
Bucket::~Bucket() 
{ 
    if (prev) 
    { 
     if (next) 
     { 
      prev->next = next; 
     } 
     else 
     { 
      prev->next = NULL; 
     } 
    } 
    if (next) 
    { 
     if (prev) 
     { 
      next->prev = prev; 
     } 
     else 
     { 
      next->prev = NULL; 
     } 
    } 
    delete [] Bucket::str; 
} 

जब त्रुटि फेंक दिया जाता है, ऐड विधि इस प्रकार है 'की सूची में' वर्ग के सदस्य विधि संलग्न है, जो काम करता है से बुलाया जा रहा है:

void BucketString::append (std::string& line) 
{ 
    length += line.length(); //Just a way to store the length of the string stored in this BucketString object 

    if (!head) //If the head node pointer is currently null, create a new head pointer 
    { 

     head = new Bucket(bucketSize); 
    } 

    Bucket* tmp = head; 

    while (tmp->next) //Finds the tail node 
    { 
     tmp = tmp->next; 
    } 
    tmp->add(line); //Calls the Bucket add function on the tail node 
} 

हेडर फाइल बाल्टी वर्ग के लिए है:

#include <cstddef> 
#include <string> 
#include <iostream> 

#ifndef BUCKET_H_ 
#define BUCKET_H_ 

namespace RBNWES001 
{ 
class Bucket 
{ 

    public: 
     //Special members and overloaded constructor 
     Bucket(void); 
     Bucket(std::size_t); 
     Bucket(const Bucket&); 
     ~Bucket(); 
     //Copy Assignment not included because it's not needed, I'm the only one who is gonna use this code! :) 

     //Add method 
     void add(std::string); 

     int filled; 
     char* str; 
     Bucket* next; 
     Bucket* prev; 
     std::size_t bucketSizeB; 
}; 
} 

#endif 
+1

एसओ में आपका स्वागत है, लेकिन मुझे आपसे पूछने दो: आपने क्या प्रयास किया है? क्या आपने यह देखने के लिए प्रिंट-स्टेटमेंट जोड़ा है कि त्रुटि कहां से आती है? क्या आपने डीबगर का इस्तेमाल किया है? (और नहीं, आपके द्वारा दिखाया गया कोड पर्याप्त नहीं है) –

+0

मैंने प्रिंट स्टेटमेंट्स को जोड़ा है, जो मुझे पता है कि इस विधि को कब बुलाया जा रहा है। अजीब चीज यह है कि विधि पहले 70 या तो वर्णों के लिए ठीक से काम करने लगती है, लेकिन फिर संदेश फेंक दिया जाता है। आपको और क्या पसंद आएगा? दुर्भाग्य से 'सूची' वर्ग बहुत लंबा है, मैं 'सूची' वर्ग (जिसे बकेटस्ट्रिंग कहा जाता है) में विधि शामिल करूंगा जो इस विधि को कॉल करता है, अगर यह कुछ हद तक मदद करता है। – wesrobin

+0

खराब_लोक को ऑपरेटर द्वारा फेंक दिया जाता है जब यह स्मृति से बाहर होता है। चूंकि ऐड रिकर्सन का उपयोग करता है, शायद आप स्मृति से बाहर निकल रहे हैं। – engineerC

उत्तर

5

यह काम करता है: मेरी Bucket(std::size_t bucketSizeB) निर्माता में str के प्रारंभकर्ता को str(new char[bucketSizeB] से str(new char[bucketSizeB_]) (यानी। कोस को पारित तर्क का उपयोग करना चाहिए) bucketSizeB चर का उपयोग करने के बजाय ntructor)।

+0

क्योंकि सदस्यों को क्रम में प्रारंभ किया जाता है, उन्हें घोषित किया जाता है। यदि आपके कंपाइलर सेटिंग्स पर्याप्त हैं तो आपको इसके लिए चेतावनी मिलनी चाहिए। – GManNickG

+1

@GManNickG, मुझे नहीं लगता कि आपको उसकी विशिष्ट त्रुटि के लिए चेतावनी क्यों मिलेगी। 'BucketSizeB' चर को पहले वैश्विक के रूप में परिभाषित किया गया था ... –

5

1) आप एक आज़माएं/कैच ब्लॉक के साथ समापन रोका जा सकता है।

2) ऐसा लगता है कि जब आप प्रोग्राम निष्पादित करते हैं तो ऐसा होता है। यह "मेक" प्रोग्राम को स्वचालित रूप से निष्पादित करने जैसा लगता है। सही बात?

3) यदि ऐसा है, तो आप एक डीबगर में देखना चाहते हैं और सटीक रेखा की पहचान करना चाहते हैं जहां यह क्रैश हो रहा है।

4) मुझे संदेह है कि क्या आप कोड के माध्यम से पता लगाते हैं कि आप देखेंगे कि एक या अधिक "diff", "bucketSizeB" और/या "भरा" बहुत बड़ा (या नकारात्मक) बन जाता है। जो एक बग होगा :) जिसे आप आसानी से ठीक कर सकते हैं - एक बार जब आप इसे पाते हैं।

5) यहाँ है, GDB पर अच्छा ट्यूटोरियल हैं कि यदि आप के लिए एक सुविधाजनक डिबगर होता है:

http://dirac.org/linux/gdb/

http://www.cs.cmu.edu/~gilpin/tutorial/

http://www.cprogramming.com/gdbtutorial.html

+0

1) त्रुटि को छुपाता है और चीजों को और भी खराब करता है, यह समस्या को हल नहीं करेगा। 2) अप्रासंगिक है। 3) एक टिप्पणी (पहले से ही) होना चाहिए। –

संबंधित मुद्दे