سؤال

عند محاولة إنشاء مثيل فئة الظاهري طريقة ونقله إلى pthread_create, أحصل على شرط سباق ، مما تسبب المتصل في بعض الأحيان استدعاء قاعدة الأسلوب بدلا من المستمدة من طريقة كما ينبغي.بعد غوغلينغ pthread vtable race, اكتشفت هذا هو إلى حد ما معروفة السلوك.سؤالي هو ما هو وسيلة جيدة للحصول على من حوله ؟

رمز أدناه يسلك هذا السلوك في أي الإعداد الأمثل.علما بأن MyThread الكائن هي التي شيدت بشكل كامل قبل أن يتم تمريرها إلى pthread_create.

#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Thread {
    pthread_t thread;

    void start() {
        int s = pthread_create(&thread, NULL, callback, this);
        if (s) {
            fprintf(stderr, "pthread_create: %s\n", strerror(errno));
            exit(EXIT_FAILURE);
        }
    }
    static void *callback(void *ctx) {
        Thread *thread = static_cast<Thread*> (ctx);
        thread->routine();
        return NULL;
    }
    ~Thread() {
        pthread_join(thread, NULL);
    }

    virtual void routine() {
        puts("Base");
    }
};

struct MyThread : public Thread {
    virtual void routine() {

    }
};

int main() {
    const int count = 20;
    int loop = 1000;

    while (loop--) {
        MyThread *thread[count];
        int i;
        for (i=0; i<count; i++) {
            thread[i] = new MyThread;
            thread[i]->start();
        }
        for (i=0; i<count; i++)
            delete thread[i];
    }

    return 0;
}
هل كانت مفيدة؟

المحلول

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

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

وجرب هذا، فإنه سوف تظهر كيفية دمر في objs من الترابط الرئيسي يستخدم موضوع قبل ولدت لهم:

struct Thread {
pthread_t thread;
bool deleted;

void start() {
    deleted=false;
    int s = pthread_create(&thread, NULL, callback, this);
    if (s) {
            fprintf(stderr, "pthread_create: %s\n", strerror(errno));
            exit(EXIT_FAILURE);
    }
}
static void *callback(void *ctx) {
    Thread *thread = static_cast<Thread*> (ctx);
    thread->routine();
    return NULL;
}
~Thread() {
    pthread_join(thread, NULL);
}

virtual void routine() {
    if(deleted){
        puts("My child deleted me");
    }
    puts("Base");
}
};

struct MyThread : public Thread {
virtual void routine() {

}
~MyThread(){
    deleted=true;
}

};

في الجانب الآخر إذا كنت مجرد مكان النوم في main قبل حذفها عليك أبدا أن المشكلة لأن موضوع لدت يستخدم موارد صالحة.

int main() {
const int count = 20;
int loop = 1000;

while (loop--) {
    MyThread *thread[count];
    int i;
    for (i=0; i<count; i++) {
            thread[i] = new MyThread;
            thread[i]->start();
    }
    sleep(1);
    for (i=0; i<count; i++)
            delete thread[i];
}

return 0;
}

نصائح أخرى

لا تفعل pthread_join (أو أي عمل حقيقي) في المدمر.إضافة الانضمام إلى() طريقة الخيط يطلق عليه قبل حذف الموضوع[أنا] في الرئيسية.

إذا كنت تحاول الاتصال pthread_join في المدمر, موضوع قد يكون لا يزال تنفيذ موضوع::روتين().مما يعني أنه باستخدام كائن بالفعل دمرت جزئيا.ما الذي سيحدث ؟ من يدري ؟ نأمل أن البرنامج سوف تحطم بسرعة.


بالإضافة إلى ذلك:

  • إذا كنت ترغب في أن ترث من خيط موضوع::~الموضوع يجب أن تعلن الظاهري.

  • التحقق من جميع الأخطاء و التعامل معها بشكل صحيح (والتي بالمناسبة لا يمكن أن يتم داخل المدمر).

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