سؤال

لدي متجه من المؤشرات إلى الفصل. أحتاج إلى استدعاء المدمرات الخاصة بهم وخالية من ذاكرتهم. نظرا لأنهم متجهون من Vector.Clear () لا يقومون بالوظيفة. لذلك ذهبت للقيام بذلك يدويا مثل:

void Population::clearPool(std::vector<Chromosome*> a,int size)
{
    Chromosome* c;
    for(int j = 0 ;j < size-1;j++)
    {
       c = a.back();
       a.pop_back();
       delete c;
       printf("  %d \n\r",j);
       c = NULL;

    }

}

الحلقة الثابتة موجودة منذ أن حصلت على Destructor Talking لمعرفة أي كروموسوم خطأ تجزئة يحدث. عندما يسمى ClearPool () ونقول أننا حصلنا على حجم 100، فيمكنه إعطاء خطأ تجزئة في أي كروموسوم بين 0 و 100.

ليس لدي أي فكرة عن سبب حدوث ذلك أو أن لدي طريقة للعثور عليها بالفعل ما هو الخطأ لأنه أثناء تصحيح الأخطاء مع كل ما أراه هو أنه يحدث هناك عند الكروموسومات العشوائية.

أنا أستخدم CodeBlocks IDE ومصحح GDB. تتبع المكدس عندما يحدث خطأ تجزئة لديه 4 عناوين ذاكرة ووظيفة wsncpy().

هل كانت مفيدة؟

المحلول

void Population::clearPool( std::vector <Chromosome*> & a )
{
   for ( int i = 0; i < a.size(); i++ ) {
      delete a[i];
   }
   a.clear();
}

لاحظ أن المتجه يتم تمريره حسب المرجع. في التعليمات البرمجية الخاصة بك، يتم استخدام نسخة من المتجه، مما يعني أنه لم يتغير في برنامج الاتصال. نظرا لحذف المؤشرات في النسخة، أصبحت المؤشرات في الأصل الآن جميعا غير صالحة - أظن أنك تستخدم تلك المؤشرات غير الصحيحة بطريقة ما لا تظهر في التعليمات البرمجية التي نشرتها.

كما تم نشر حلول القالب التي تستخدم خوارزميات مكتبة C ++، قد ترغب أيضا في النظر في حل القالب الذي لا:

template <class C> void FreeClear( C & cntr ) {
    for ( typename C::iterator it = cntr.begin(); 
              it != cntr.end(); ++it ) {
        delete * it;
    }
    cntr.clear();
}

باستخدام هذا يمكنك المجانية أي حاوية من الكائنات المخصصة ديناميكيا:

vector <Chromosome *> vc;
list <Chromosome *> lc;
// populate & use
FreeClear( lc );
FreeClear( vc );

نصائح أخرى

نسخة معدلة خفيفة مقارنة ب (@ 1800 معلومات).

  struct DeleteFromVector
    {
        template <class T>
        void operator() ( T* ptr) const
        {
            delete ptr;
        }
    };


std::for_each(aVec.begin(), aVec.end(), DeleteFromVector());

لا أعرف لماذا تعطل، لكنني أعتقد أن احتمال واحد هو أن حجم المتجه ليس هو نفسه الحجم الذي تذهب فيه. كما لاحظت أنك تكرار من 0 إلى الحجم - 2، هل أنت لا يعني الذهاب طوال الطريق إلى النهاية؟

طريقة واحدة لحذف جميع العناصر الموجودة في الصفيف باستخدام Itiomatic C ++ هو شيء مثل هذا:

template<class T>
class deleter
{
  public:
    void operator()(const T* it) const
    {
      delete it;
    }
};

std::for_each(a.begin(), a.end(), deleter<Chromosome>());

يحتوي Boost Lambda بالفعل على Functor لحذف تسلسل المؤشرات، بالمناسبة:

std::for_each(a.begin(), a.end(), boost::lambda::delete_ptr());

هل أنت متأكد من أن كل مؤشر في الموجه يشير إلى كائن مختلف؟ (أي أن اثنين من المؤشرين لا يشيران إلى نفس الكائن، الذي تحاول حذف مرتين.

هل أنت متأكد أنك لا تحذف بعض المؤشرات قبل الاتصال بهذه الطريقة؟ (أي هل أنت متأكد من أن كل مؤشر في القائمة يشير إلى كائن صالح؟)

السبب الأكثر احتمالا هو الدعوة حذف مرتين لنفس العنوان. يمكن أن يحدث هذا إذا أضفت كائن واحد أكثر من مرة إلى المتجه. للكشف عن هذا الإدراج بعض البيان الذي سيخرج عنوان الكائن الذي ستحتاج إليه بعد ذلك حذف.

printf( "will delete %d\n", (int)c );
delete c;

لقد وجدت المشكلة.

كان في الجزء الأكثر مخفية (من قبل لا شيء آخر غير me old me) قد يكون.

لأن البعض قد خمنت هذه برنامج خوارزميات وراثية. هو لبرنامج تعليمي أقوم به. كنت اختر نقاط كروموسومات للكروموسومات بشكل عشوائي من وظيفة عجلة الروليت التي صنعتها. حسنا ... داخل هناك، كان هناك -1-1 لا ينبغي أن يكون هناك. التي دمرت حرفيا كل شيء، وفي النهاية تؤدي إلى خطأ تجزئة.

شكرا لكم جميعا على مساعدتكم، رأيت بعض الممارسات الجيدة حقا في هذا المنصب الذي أنوي متابعة

أوصي باستخدام مؤشر ذكي (أي: auto_ptr) بدلا من المؤشر الخام واستخدام فقط الأسلوب المتجه :: مسح الطريقة التي ستدعو المدمر لكل عنصر

void Population::clearPool(std::vector<Chromosome*>& a)
{
    for(size_t i = 0; i < a.size(); i++) {
        delete a[i];
    }

    a.clear();
}

يبدو أن بعض المؤشرات في التعليمات البرمجية لا تشير إلى كائنات الكروموسوم الصحيحة. قد يحدث هذا، إذا حاولت حذف بعض الكائنات مرتين نتيجة لكود:

Population p;
vector<Chromosome*> chromosomes;
p.clearPool(chromosomes,chromosomes.size()); // You pass by value, so chromosomes is not changed
p.clearPool(chromosomes,chromosomes.size()); // Delete already deleted objects second time

قد تجد ptr_vector مفيدة من مكتبة حاويات المؤشر من أجل تجنب أخطاء مماثلة

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top