Доступ к глобальному списку с помощью PThreads - проблема с указателем? - PullRequest
2 голосов
/ 08 декабря 2011

Мы выполняем проект с использованием потоков и мьютексов, чтобы имитировать группу клиентов, использующих разные или одинаковые банковские счета У меня практически нет опыта работы с C / C ++, и я думаю, что эта проблема связана с указателями. В основном у меня есть объект Client, который содержит список транзакций и список учетных записей и который передается в качестве параметра в pthread, где он отправляется в метод обработки.

class Client{
public:
    list<Transaction> transactions;
    list<Account>* accounts;
    Client(list<Transaction>, list<Account>);
};

Client::Client(list<Transaction> a, list<Account> b){
transactions = a;
accounts = &b;
}

extern "C"
{
void* RunTransactions(void* arg)
{
    Client* c = static_cast<Client*>(arg);

    // while(!(*c).transactions.empty()){
        // cout << "HERE" << endl;
    // }

    cout << "Thread Before: ";
    (*(*c).accounts).front().Print();

    (*(*c).accounts).front().balance -= 25;
    (*(*c).accounts).front().balance -= 25;
    (*(*c).accounts).front().balance -= 25;

    cout << "Thread After: ";
    (*(*c).accounts).front().Print();

    // list<Transaction>* trans = static_cast<list<Transaction>*>(arg);
    // Transaction t = trans->front();
    // t.Print();

    // Test* t = static_cast<Test*>(arg);

    // (*t).Increase();
    // cout << "Thread - " << t->x << endl;

    return 0;
}
}

int main( ){

list<Account> accounts;

cout << "Accounts: ";
cin >> NumAccts;

for(long i = 0; i < NumAccts; i++){
    long tempBalance;
    cout << "Balance for Account " << i << ": ";
    cin >> tempBalance;

    accounts.push_back(Account(i, tempBalance));
}

//Test Input
pthread_t t1;
list<Transaction> tempTrans;
tempTrans.push_back(Transaction(0, 1, 100));
tempTrans.push_back(Transaction(1, 0, 50));
tempTrans.push_back(Transaction(2, 1, 222));

Client c = Client(tempTrans, accounts);

cout << "Main Before: ";
accounts.front().Print();

pthread_create(&t1, NULL, RunTransactions, &c);

pthread_join(t1, NULL);

cout << "Main After: ";
accounts.front().Print();


return 0;
}

Чего я не понимаю, так это как все мои потоки должны иметь доступ к списку учетных записей, который создается в main? Прямо сейчас, когда я что-то делаю со списком учетных записей, который я извлекаю из клиента, он вносит изменения в поток, но я не вижу изменений в списке учетных записей в основном после объединения. Опять же, я думаю, что это связано с тем, как я передаю или получаю доступ к учетным записям в объекте Client или в main, или, возможно, RunTransactions? Любой совет будет высоко ценится!

Ответы [ 2 ]

1 голос
/ 08 декабря 2011
Client::Client(list<Transaction> a, list<Account> b) {

b - копия переданного списка, и почти наверняка будет передана в стек. Как только конструктор вернется, ваш указатель, вероятно, недействителен.

Вы бы лучше сделали accounts своего клиента реальным списком, а не указателем на него. Вы действительно не хотите, чтобы ваш объект содержал указатель на что-то, что не было выделено в куче, или что кто-то другой имеет доступ к нему. Так лежит безумие.

0 голосов
/ 08 декабря 2011
Client::Client(list<Transaction> a, list<Account> b){
    transactions = a;
    accounts = &b;
}

В основном говорит: «О да, Рой, у тебя есть этот список здесь, верно, со всеми этими учетными записями? Ну, кто-то прислал мне его по электронной почте, ты можешь увидеть, откуда пришел этот список, и просто сохранить имя кого создал список? Я уверен, что мы сможем получить список обратно с этого адреса позже. "

Итак, Рой сохраняет имя «Уолдо» в профиле клиента. Мы все знаем, что случилось после этого. К сожалению, он так и не смог получить список снова, когда клиент попросил его. Если бы только он сделал копию списка или убедился, что источник, создавший список, не исчезнет однажды.

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