Добрый день, друзья.
При написании многопоточного сервера столкнулся со странной проблемой.
Попробую как могу описать суть.
Вначале всё работало и выглядело примерно так:bool TCP_parent::listen() {
int new_socket = ::accept(...);
pthread_create(&thread1, NULL, start_routine, (void*) &socket);
}Потом я переместил вызов функции pthread_create в дочерний класс, точнее переопределил родительский метод TCP_parent::accept:
bool TCP_parent::listen() {
int new_socket = ::accept(...);
accept(new_socket);
}bool TCP_child::accept(int sock) {
pthread_create(&thread1, NULL, start_routine, (void*) &sock);
}После этой безобидной операции функция потока start_routine перестала получать свой аргумент sock. Точнее после разыменования аргумента *((int*)ptr) получалось что-то неудобочитаемое, типа 134515204. Может в g++ не работает как надо полиморфизм?
# uname -a
FreeBSD srv-prog2.ru 8.1-RELEASE FreeBSD 8.1-RELEASE #0: Mon Jul 19 02:55:53 UTC 2010 root@almeida.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386# g++ --version
g++ (GCC) 4.2.1 20070719 [FreeBSD]
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Всем спасибо, причину нашёл.
Неверно определил аргумент:-bool TCP_child::accept(int sock)
+bool TCP_child::accept(const int& sock)
> bool TCP_parent::listen() {
> int new_socket = ::accept(...);
> pthread_create(&thread1, NULL, start_routine, (void*) &socket);
> }Вы, конечно, понимаете, да, что передаете в функцию которая запускается во втором thread'e адрес локальной переменной которая размещеня в стеке перого thread'a? (В смысле, что нет никакой гарантии что в тот момент когда start_routine() во втором thread'е попытается прочитать значение типа int по этому адресу, TCP_parent::listen() в первом thread'е уже может завершится и ее локальнй переменной new_socket (адрес которой и был передан) может не существовать?)
>> bool TCP_parent::listen() {
>> int new_socket = ::accept(...);
>> pthread_create(&thread1, NULL, start_routine, (void*) &socket);
>> }
> Вы, конечно, понимаете, да, что передаете в функцию которая запускается во
> втором thread'e адрес локальной переменной которая размещеня в стеке перого thread'a?
> (В смысле, что нет никакой гарантии что в тот момент когда
> start_routine() во втором thread'е попытается прочитать значение типа int по этому
> адресу, TCP_parent::listen() в первом thread'е уже может завершится и ее локальнй
> переменной new_socket (адрес которой и был передан) может не существовать?)Это я упустил. Получается, надо создать динамическую переменную:
bool TCP_parent::listen() {
int* new_socket = new int( ::accept(...) );
pthread_create(&thread1, NULL, start_routine, (void*) new_socket);
}- а функция start_routine должна взять на себя уничтожение этой переменной.
Да, всё заработало. Вы ответили на мой вопрос. Большое спасибо!