Создано больше тем, чем ожидалось

Вы можете найти программу здесь

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

Программа составлена ​​с g++ -std=c++11 test.cpp -o test -lzmq -lpthread,

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

В основной теме я настраиваю тему с:

  vector<thread> pool;
  for(int i = 0; i < worker_num; i++)
  {
    cout << "main() : creating thread, " << i << endl;
    pool.push_back(thread(task1, (void *)&context, i));
  }

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

  while(true)
  {
    if(sync_done)
    {
      cout << "sync done in main thread" << endl;
      break;
    }

    zmq::message_t sync_msg(4);
    memcpy((void *)sync_msg.data(), SYNC_MSG, SYNC_MSGLEN);
    for(int i = 0; i < worker_num; i++)
      distask_socket.send(sync_msg);

    for(int i = 0; i < worker_num; i++)
    {
      if(sync_done)
        break;
      if(i != 0)
        this_thread::sleep_for(chrono::milliseconds(500));

      zmq::message_t res_msg;
      int ret = getres_socket.recv(&res_msg, ZMQ_DONTWAIT);

      if(ret == -1 && errno == EAGAIN)
        continue;

      int threadID = stoi(string((char *)res_msg.data()));
      sync_done = if_sync_done(threadID, sync_array, worker_num);
    }
  }

Итак, что основной поток делает: нажатие #worker_num из sync msgs с его конечной точкой PUSH для рабочих потоков каждый раз, а затем читает подтверждающее сообщение msg из своей конечной точки PULL. Если основной поток получает #worker_num сообщений с подтверждением, то синхронизация выполнена. Формат сообщения синхронизации от работника: идентификатор рабочего потока в строке. Таким образом, поток 0 будет проходить 0 в строке вернуться к основному потоку.

Но запущенная программа у меня есть:

$ ./test 1
main() : creating thread, 0
thread id:0
thread 0 receives: sync
thread 0 sends: 0
thread 0 sync done
main thread receives sync msg from thread 1 # you may get many copies of this msg
terminate called after throwing an instance of 'std::invalid_argument'
  what():  stoi
Aborted

main thread receives sync msg from thread 1 означает, что потоки созданы 2 темы: нить 0 и нить 1. Есть идеи, почему? Я прошел 1 в качестве параметра. Заметил, что если вы запустите программу самостоятельно, вы можете получить другие результаты.

ОБНОВИТЬ:

Программа обновлена: здесь.

Наконец я понял, что не так.

ожидаемый результат, вы видите поток 0 передать 0 в основной поток, чтобы уведомить синхронизацию сделано:

$ ./test 1
input parameter is: 1
main() : creating thread, 0
thread 0 receives: sync
to_string 0
thread 0 sends: 0, with size: 1
thread 0 sync done
pass 0 to if_sync_done
main thread receives sync msg from thread 0
sync done in main thread

неожиданный вывод, вы видите непечатаемый символ передается stoi():

$ ./test 1
input parameter is: 1
main() : creating thread, 0
thread 0 receives: sync
to_string 0
thread 0 sends: 0, with size: 1
thread 0 sync done
pass  to if_sync_done  # !!!!!
terminate called after throwing an instance of 'std::invalid_argument'
  what():  stoi
Aborted

Так что кажется, что я использую message_t неправильно. Поэтому я должен убедиться, что перед тем, как основной поток передает содержимое stoi(), буфер все еще существует.

Я сам добавлю ответ.

1 ответ

Решение
zmq::message_t msg_back((void *)to_string(id).c_str(), to_string(id).size() + 1, NULL);

zmq::message_t используемый вами конструктор не создает копию буфера, если верить [1] и [2]. Вместо этого он становится владельцем буфера.

Тем не менее, вы передаете буфер, управляемый временным; этот буфер уничтожается, как только возвращается конструктор. У тебя есть msg_back хранить висячий указатель. Любая попытка использовать этот указатель - например, попытка прочитать сообщение на принимающей стороне - демонстрирует неопределенное поведение.

Другие вопросы по тегам