Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Передача параметров в CreateThread  (Прочитано 21128 раз)
0 Пользователей и 1 Гость смотрят эту тему.
LightSin
The question title sounds to me the same as "Convert banana into a pistol"... :-)
Постоялец

ru
Offline Offline
id/fm105


« : 19-10-2011 20:39 » 

Пытаюсь передать параметры, с 1 параметром работает нормально, но когда передаю через структуру этот же параметр - получается что передается не то значение...
вариант 1 рабочий..
Код: (Text)
int* csock;
        sockaddr_in sadr;
        int     addr_size = sizeof(SOCKADDR);
       
        while(true){
                printf("waiting for a connection\n");

                 csock = (int*)malloc(sizeof(int));

                if((*csock = accept( listenfd, (SOCKADDR*)&sadr, &addr_size))!= INVALID_SOCKET ){

                        printf("\nReceived connection from %s\n",inet_ntoa(sadr.sin_addr));
                       
             CreateThread(0,0,&SocketHandler, (void*)csock , 0,0);
                }
                else{
                        fprintf(stderr, "Error accepting %d\n",WSAGetLastError());
                }
        }
 
Цитата: созданный поток
DWORD WINAPI SocketHandler(void* lp){

   int *csock = (int*) lp;
Вот, это работает.
1 заход в цикл While, первый вызов csock = (int*)malloc(sizeof(int)); ( 0x00366be0 = -842150451)
далее вызов *param.csock = accept.. и по этому адресу(0x00366be0) присваивается значение 3992
2 заход в цикл вызов csock = (int*)malloc(sizeof(int)); ( 0x00366b20 = -842150451)
но при *param.csock = accept.. отладчик сразу переходит в код созданного потока.

в потоке  csock = (int*)malloc(sizeof(int)); получает 0x00366be0 = 3992
 то адрес из 1 захода цикла...

вариант 2
Код:
struct tagParam
    {
      int* csock;
      char* file;
    };
CreateThread(0,0,&SocketHandler, &param, 0,0);
   1 заход в цинкл *csock получает 0x00366be0 = 3992 (все также)
       2 заходи в цкикл  *csock получает  0x00366b20 = -842150451
в потоке int *csock = (int*)param->csock; но получает 0x00366b20 = -842150451)
то есть..   передав адрес структуры.. но в ней изменилось значение... как-то так..

как правильно сделать? уф надеюсь смысл донес..  С ума сойти...
мм то есть надо не адрес структуры передать.. а саму структуру копию.. наверн..



Добавлено через 6 минут и 51 секунду:
сделал ... хитрожопно работает но хотелось бы по нормальном  Меня одолевают смутные сомнения
« Последнее редактирование: 19-10-2011 21:03 от LightSin » Записан

Lost in the jungle: 1c, PIC AVR, C++, Python flask, (no Java) JS . for fun: Live For Speed S2 Drift Edition, TeeWorlds
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 20-10-2011 03:51 » 

указатель на локальную переменную передаёшь, поди ?
Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 20-10-2011 08:29 » 

Код: (C)
void s_f(void *p) {
  int *px = (int *)p;
  *px = 5;
}

int main() {
  int x = 3;
  s_f(&x); /* типа синхронный вызов */
  /* определённо x == 5 */
  return 0;
}
Передаёшь внутрь f адрес на локальную переменную x. Можешь ей манипулировать. Но main не завершит работу раньше, чем завершит работу f из-за синхронности вызовов. Значит x внутри main будет сохраняться всё время вызова. Запуск нити - это по сути асинхронный вызов. С этого момента нельзя предсказать, что раньше сработает: продолжение main или f. Поэтому нельзя передавать локальную переменную из main - может так случиться, что main закончит работу и удалит переменную до того, как f ею захочет воспользоваться. Переменная должна быть глобальной. Глобальная переменная объявляется либо вне функций, либо память для неё выделяется в куче. Например, через кучу.
Код: (C)
void a_f(void *p) {
  int *px = (int *)p;
  *px = 5;
  free(px); /* не забыли удалить из кучи глобальную переменную */
}
int main() {
  int *px = (int *)malloc(sizeof(int)); /* завели глобальную переменную в куче */
  *px = 3;
  a_f(px); /* типа асинхронный вызов */
  /* дальнейшая судьба x с этого места внутри main непредсказуема */
  return 0;
}
Здесь важно, что если f асинхронно, то после этого вызова для main значение *px становится неопределённым - может успеет f его изменить, а может и не успеет. Если надо несколько переменных, то упаковываем их в структуру.
Код: (C)
struct s {
  int x;
};

void a_f(void *p) {
  struct *ps = (struct s *)p;
  ps->x = 5;
  free(ps);  /* не забыли удалить из кучи область памяти с глобальными переменными */
}

int main() {
  struct s *ps = (struct s *)malloc(sizeof(struct s)); /* завели в куче область памяти с глобальными переменными */
  ps->x = 3;
  a_f(ps); /* типа асинхронный вызов */
  /* дальнейшая судьба всех глобальных переменных с этого места внутри main непредсказуема */
  return 0;
}
Аналогично, после асинхронного вызова f для main значения в структуре становятся неопределёнными.

Обрати внимание, что внутри структуры не указатели, а значения. Если ты хочешь передать указатели на локальные переменные - это в корне неверно для асинхронных вызовов. А выделять память в куче под числа внутри структуры бессмысленно, т.к. вся структура уже в куче, и эти числа уже не являются локальными.
« Последнее редактирование: 20-10-2011 08:45 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
LightSin
The question title sounds to me the same as "Convert banana into a pistol"... :-)
Постоялец

ru
Offline Offline
id/fm105


« Ответ #3 : 20-10-2011 09:00 » 

Цитата: Алексей1153++
указатель на локальную переменную передаёшь, поди ?
да, все передается норм, проблема в 2 цикле что он изменяет.

Цитата: Dimka
Если ты хочешь передать указатели на локальные переменные - это в корне неверно для асинхронных вызовов.
хех, правильней будет глобальные передавать?


добавил param.ssock =(int) param.csock;
добавил int *csock = (int*)param->ssock;
Цитата
struct tagParam
    {
      int *csock;
     int ssock;
      char* file;
    };
Код:
  tagParam param;
    param.file=path_way;

sockaddr_in sadr;
int addr_size = sizeof(SOCKADDR);

while(true){
printf("waiting for a connection\n");
param.csock = (int*)malloc(sizeof(int));
if((*param.csock = accept( listenfd, (SOCKADDR*)&sadr, &addr_size))!= INVALID_SOCKET ){
param.ssock =(int) param.csock;
printf("\nReceived connection from %s\n",inet_ntoa(sadr.sin_addr));
CreateThread(0,0,&SocketHandler,&param, 0,0);
}
else{
fprintf(stderr, "Error accepting %d\n",WSAGetLastError());
}
}

FINISH:
;
}

DWORD WINAPI SocketHandler(LPVOID lp){
tagParam *param = (tagParam*)lp;
int *csock = (int*)param->ssock;
char *cfile = param->file;
« Последнее редактирование: 20-10-2011 09:02 от LightSin » Записан

Lost in the jungle: 1c, PIC AVR, C++, Python flask, (no Java) JS . for fun: Live For Speed S2 Drift Edition, TeeWorlds
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 20-10-2011 10:10 » 

Цитата: LightSin
хех, правильней будет глобальные передавать?
Ещё раз читай то, что я написал про локальные и глобальные переменные. Читай до победы, поскольку твоё решение полностью игнорирует мною сказанное.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 20-10-2011 16:02 » 

LightSin, нужно передавать указатель на динамически созданную переменную. Ну и не забывать удалять тоже потом
Записан

LightSin
The question title sounds to me the same as "Convert banana into a pistol"... :-)
Постоялец

ru
Offline Offline
id/fm105


« Ответ #6 : 20-10-2011 21:32 » 

Цитата: Алексей1153++
нужно передавать указатель на динамически созданную переменную. Ну и не забывать удалять тоже потом
ок, шеф)    free(csock); в потоке освобождается.. вроде норм робит все
Записан

Lost in the jungle: 1c, PIC AVR, C++, Python flask, (no Java) JS . for fun: Live For Speed S2 Drift Edition, TeeWorlds
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 20-10-2011 22:10 » 

Цитата: LightSin
вроде норм робит все
Рисковый ты парень, как я погляжу. Так что потом не ной - тебя предупреждали.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алик
Постоялец

kz
Offline Offline

« Ответ #8 : 23-10-2011 04:53 » new

LightSin, имеется в виду, что переменная типа "tagParam" сама должна располагаться в динамической памяти.
а твой вариант - не вариант  Не надо
Записан
LightSin
The question title sounds to me the same as "Convert banana into a pistol"... :-)
Постоялец

ru
Offline Offline
id/fm105


« Ответ #9 : 31-10-2011 00:35 » 

Цитата
твой вариант - не вариант  Не надо
Эт точно, понял в чем проблема... почему такой вариант работает...дело во времени...

При создание потока, указатель  на созданный сокет, передаться не успевает, а передается указатель на след вызов цыкала , accept возвращает прослушку и param.csock = new int; скажем так... путем эксперимента
Код:
	while(true){
printf("waiting for a connection\n");
param.csock = new int;
if((*param.csock = accept( listenfd, (SOCKADDR*)&sadr, &addr_size))!= INVALID_SOCKET ){
printf("\nReceived connection from %s-%s\n",inet_ntoa(sadr.sin_addr),param.ip);
CreateThread(0,0,&SocketHandler,&param, 0,0);
Sleep(200); //при меньших значениях вылит
}
else{
fprintf(stderr, "Error accepting %d\n",WSAGetLastError());
}
}
как сделать правильно? чтоб выполнение мэйна было приостановлено до передачи всех значений...в поток.
Код:
DWORD WINAPI SocketHandler(LPVOID lp){
tagParam *param = (tagParam*)lp;
       int *csock = param->csock;
char *cfile = param->file;

Цитата: Dimka
понял о чем говорил. поздно ) правд
« Последнее редактирование: 31-10-2011 00:53 от LightSin » Записан

Lost in the jungle: 1c, PIC AVR, C++, Python flask, (no Java) JS . for fun: Live For Speed S2 Drift Edition, TeeWorlds
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 31-10-2011 08:52 » 

Цитата: LightSin
чтоб выполнение мэйна было приостановлено до передачи всех значений...в поток
Это неправильно. Вообще тормозить потоки - неправильно, крайняя мера. Твоя задача решается без всяких торможений. Конечно, если ты всё-таки внимательно прочитаешь мною написанное насчёт структуры и её содержимого.

Вообще главный поток записывает значения в структуру-параметр дочернего потока. Поэтому заявление об ожидании звучит странновато. Не может главный поток обогнать сам себя - чего тогда ему ждать? Это какое-то странное представление о происходящем.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
LightSin
The question title sounds to me the same as "Convert banana into a pistol"... :-)
Постоялец

ru
Offline Offline
id/fm105


« Ответ #11 : 31-10-2011 20:42 » 

Цитата
Не может главный поток обогнать сам себя - чего тогда ему ждать?
Указатель  *param.csock = accept , проблеме передачи его в структуре,
при вызове все нормально передается.. CreateThread(0,0,&SocketHandler,&param, 0,0);
но в потоке получить   *param.csock не получается так как мэин успел сделать  param.csock = new int;
притормозив мэин ,создастся поток ,передаться все успевает,  все работает...

думаю может сделать * на  bool переменную в структуре передаваемой.. в значение 0.. и в потоке изменить это значение когда все параметры передадутся..
в мэине не давать выполнять след функцию пока поток  не изменит  bool в 1 ( проверил робит)
« Последнее редактирование: 31-10-2011 20:57 от LightSin » Записан

Lost in the jungle: 1c, PIC AVR, C++, Python flask, (no Java) JS . for fun: Live For Speed S2 Drift Edition, TeeWorlds
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 31-10-2011 22:07 » 

LightSin, тогда дело не в указателях, а в том, что ты не понимаешь понятие "экземпляр" (instance). И не видишь разницы между переменной как идентификатором в исходном коде и как областью памяти, хранящей значение во время исполнения. Короче говоря, шаманишь.

Экземпляр потока и экземпляр его параметра (структуры) должны находиться в отношении 1 к 1. В моём примере это так. В моём же примере указано на правильное управление памятью.

Ты же пытаешься использовать shared-экземпляр параметра для всех потоков в отношении 1 ко многим. Естественно, у тебя не получается в одну переменную csock "впихнуть" несколько разных значений для разных потоков. Главный поток должен последовательно работать с разными экземплярами csock в частности и param в общем на каждой итерации цикла. Это элементарно решается при помощи динамического выделения памяти под param в каждой итерации.

Это всё элементарные вещи, которые отражены в моих примерах. Нужно лишь внимательно изучить примеры и почаще себе задавать вопросы, почему что-то сделано так, а не иначе.
« Последнее редактирование: 31-10-2011 22:09 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines