При получении доступа к нему из класса переменные теряются, когда напрямую работает нормально - PullRequest
2 голосов
/ 30 марта 2012

Ну, я пытаюсь установить переменную для использования в потоке, она прекрасно работает, если я вызываю pthread из основной функции, но если я вызываю ее из функции или функции внутри класса, переменная теряетсяи вместо этого выводит мусор, поэтому я добавил условие

if (this-> pickup <7) </p>

, поэтому я свернул код, чтобы разместить его здесь, потому чтов нем есть все примеры, о которых я говорю.

Вывод этого кода ниже:

Доступ по классу:

Привет, мир!<</p>

Прямой доступ:

Привет, мир !, N: 6 <</p>

Я хотел бы получить тот же результат, что и в случае прямого доступа в Access по классуЯ хочу, чтобы он вывел ", N: 6", потому что в конце концов он был определен.что мне здесь не хватает?

Надеюсь, я достаточно ясно, заранее спасибо.

(Кстати, я использую библиотеку pthread, доступную для Windows), так что воткод:

#include <stdio.h>
#include <pthread.h>
#include <iostream>
#include <conio.h>
#include <windows.h>

class C {
public:
    int pickup;

    void *hello()
    {
        std::cout << "\nHello, world!";

        if(this->pickup < 7)
        std::cout << ", N: " << this->pickup;

        std::cout << "<" << std::endl;
        printf("HI");
        return 0;
    }

    static void *hello_helper(void *context)
    {
        return ((C *)context)->hello();
    }


    void StartThread(){
        C c;
        c.pickup = 6;

        pthread_t t;
        pthread_create(&t, NULL, &C::hello_helper, &c);
    }


};



int main () {

    C c;
    std::cout << "Access by Class: \n";
    c.StartThread();
    c.pickup = 6;
    Sleep(2000);

    std::cout << "\nAccess Directly: \n";
    pthread_t t;
    pthread_create(&t, NULL, &C::hello_helper, &c);

    _getch();
    return 0;
}

Ответы [ 4 ]

2 голосов
/ 30 марта 2012

c уничтожается, когда возвращается StartThread(), что означает, что hello_helper() использует висячий указатель, приводящий к неопределенному поведению.

Изменить на:

void StartThread(){
    C* c = new C();
    c->pickup = 6;

    pthread_t t;
    pthread_create(&t, NULL, &C::hello_helper, c);
}

Не забудьте delete аргумент, переданный в hello_helper():

static void *hello_helper(void *context)
{
    C* c = static_cast<C*>(context);
    c->hello();
    delete c;
    return 0;
} 

EDIT:

Всегда delete аргумент, переданный в hello_helper(), предотвратит передачу объектов, выделенных стеком, в hello_helper(). Механизм должен указать hello_helper(), ответственен ли он за уничтожение своего аргумента.

1 голос
/ 30 марта 2012

C, с которого вы запускаете поток в StartThread(), выходит из области видимости и уничтожается до того, как создаваемый вами поток сможет его использовать.

Если вы знаете, что экземпляр класса, который вы вызываете StartThread(), будет существовать в течение всего потока потока, возможно, вы захотите передать this в качестве контекста, а не новый объект стека:

void StartThread() {
    pthread_t t;
    pthread_create(&t, NULL, &C::hello_helper, this);
}
0 голосов
/ 31 марта 2012

Обратите внимание, что StartThread создает объект C, который не создается ни из какого-либо материала аргумента (StartThread не принимает аргументов), ни из какого-либо материала элемента, класс которого StartThread является членом. Т.е. вы можете иметь это:

void StartThread(){
    pthread_t t;
    pthread_create(&t, NULL, &C::hello_helper, NULL);
}

// The code is easily moved into the thread.
static void hello_helper(void *)
{
   C c;
   c.pickup = 6;

}

Кроме того, возможно, что вы действительно этого хотели?

void StartThread(){
    pthread_t t;
    pickup = 6;
    // use THIS object, not some new one, doh?
    pthread_create(&t, NULL, &C::hello_helper, (void *) this);
}

т.е. может быть, вы на самом деле хотите, чтобы obj.StartThread() запускал поток, работающий с obj, а не создавал какой-то другой объект внутри?

0 голосов
/ 30 марта 2012

Вызов pthread_create() немедленно возвращается, поэтому вы выходите из функции C::StartThread до того, как ваш порожденный поток действительно сможет запустить. Таким образом, объект экземпляра C, представленный c, больше не существует, поскольку он был автоматической переменной в стеке StartThread. Необходимо убедиться, что время жизни c существует за пределами стека StartThread, что обычно выполняется с использованием динамической памяти или, возможно, статической переменной и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...