Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2009.05.24;
Скачать: [xml.tar.bz2];

Вниз

api-потоки, создание-разрушение   Найти похожие ветки 

 
Незнайка Винидиктович   (2009-03-29 18:25) [0]

Вот такая проблема случилась: Пишу подобие сокс5-сервера, с сипользование winapi-потоков, т.е. при старте запускаеться отдельный поток в котором крутиться бесконечный цикл с Accept, и как только есть подключившийся сокет, он создает поток и передает этот сокет туда... Так вот странность какая, что вродебы никаких общих переменных нету, никакой синхронизации нету(за её ненадобностью), т.е. все потоки существуют отдельно друг от друга. Так вот откудато берется ошибка памяти ((

В потоке примерно вот такая штука крутиться:

       while True do
       begin
               FD_Zero(FDSet);
               FD_Set(srv_sock,FDSet);

               //åñëè åñòü êëèåíò, òî ïåðåäàåì ñîêåò â êëèåíòñêèé ïîòîê
               Select(0,@FDSet,nil,nil,@timeout);
               if FD_IsSet(srv_sock,FDSet) then
               begin
                       accepted_sock:=Accept(srv_sock,@Addr,@addr_size);
                       CreateThread(nil, 0, @cli_thread, pointer(accepted_sock), 0, h);
               end;
       end;


Так вот кстати, как правельно разрушать потоки???
изнутри ExitThread(0); недостаточно? или как это правельно вообще делаеться?


 
Сергей М. ©   (2009-03-29 19:42) [1]


> откудато берется ошибка памяти


Она "берется" из 17-й строки в твоем коде


> изнутри ExitThread(0); недостаточно?


Достаточно.
Иногда даже излишне.


 
DVM ©   (2009-03-29 21:19) [2]


> вродебы никаких общих переменных нету

а это по твоему не общая: accepted_sock


 
Сергей М. ©   (2009-03-29 21:25) [3]


> синхронизации нету(за её ненадобностью)


Смелое заявление)


 
DVM ©   (2009-03-29 22:18) [4]


>
> Незнайка Винидиктович   (29.03.09 18:25)  

Тебе делать надо как то так:

ClientSocket := accept(ListenSocket, nil, nil);
if ClientSocket <> INVALID_SOCKET then
 begin
   New(Info);
   Info^.Socket := ClientSocket;
   hClientThread := BeginThread(nil, 0, @SocketThread, Info, 0, ThreadId);

....

где Info: PThreadData;

 ThreadData = record
   Socket: TSocket;
   .....
 end;

 PThreadData = ^ThreadData;


 
мимо   (2009-03-29 22:36) [5]


> а это по твоему не общая: accepted_sock

В коде выше - не общая.


> Тебе делать надо как то так:


Зачем усложнять? Он передает одну переменную, которая равна (по размеру) указателю (SOKET = HANDLE = LPVOID).


> Вот такая проблема случилась


А в каком месте ошибка то происходит?


 
Незнайка Винидиктович   (2009-03-29 22:51) [6]


> > откудато берется ошибка памяти
>
>
> Она "берется" из 17-й строки в твоем коде

хм. в представленом мной коде всего 13 строк.


> > изнутри ExitThread(0); недостаточно?
>
> Достаточно.
> Иногда даже излишне.

Спасибо за ответ! )


> а это по твоему не общая: accepted_sock

В данном случае accepted_sock не общая, помойму вы что-то путаете...


> > Вот такая проблема случилась
>
> А в каком месте ошибка то происходит?


Вот даже и незнаю, нету ни обших переменных ничего такого что должно было бы её вызвать и как оказалось завершаю потоки(ExitThread(0);) тоже правельно, но она подло откудато вылезает. Вылетает она в разных местах всегда, как не пытался дебагить, ничего не получилось, да и все ещё ослажняеться тем, что потоков несколько... а вообще откуда она может взяться если нету общих ресурсов ?

Я бы сюда полный листинг вывел, да пишет что ограничение по символам ((


 
Незнайка Винидиктович   (2009-03-29 23:14) [7]

ЛЮДИ! всем спасибо за ответы, проблема обнаружена!
Это было просто переполнение буфера, в самом клиентском потоке ))
Ещё раз всем спасибо!


 
DVM ©   (2009-03-29 23:30) [8]


> мимо   (29.03.09 22:36) [5]
>
>
> > а это по твоему не общая: accepted_sock
>
> В коде выше - не общая.

неправда, ты передаешь указатель в поток на переменную, дальнейшая судьба которой в основном потоке неизвестна (по крайней мере из приведенного кода)


 
DVM ©   (2009-03-29 23:33) [9]


> > мимо   (29.03.09 22:36) [5]

Как только произойдет ВТОРОЙ коннект к серверу, значение этой переменной будет переписано новым значением и кирдык.


 
DVM ©   (2009-03-29 23:37) [10]


> Незнайка Винидиктович   (29.03.09 18:25)  

Еще, ты решил использовать CreateThread вместо BeginThread, надеюсь, не забыл про выставление флага IsMultiThread := TRUE;


 
DVM ©   (2009-03-29 23:39) [11]


> мимо   (29.03.09 22:36) [5]
>
>


> Зачем усложнять? Он передает одну переменную, которая равна
> (по размеру) указателю (SOKET = HANDLE = LPVOID).

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


 
Незнайка Винидиктович   (2009-03-29 23:56) [12]

Но встал другой вопрос. С потоками все впорядке, создаються-завершаютьсьяс все ок, но вот размер приложения в процессе работы растет, из-за чего это может быть?


 
Незнайка Винидиктович   (2009-03-29 23:59) [13]

Я имел ввиду размер в памяти... (


> > мимо   (29.03.09 22:36) [5]> > > > а это по твоему не
> общая: accepted_sock> > В коде выше - не общая.неправда,
>  ты передаешь указатель в поток на переменную, дальнейшая
> судьба которой в основном потоке неизвестна (по крайней
> мере из приведенного кода)


так там все просто происходит
localpar:=lpParam;
т.е. легким движением руки она превращаеться в локальную переменную


 
мимо   (2009-03-30 00:04) [14]


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

Где там указатель? Там приведение типа SOCKET к типу Pointer. Никакого указателя там нет.

И ничего он не перезаписывает. Внимательно на код посмотрите.


 
мимо   (2009-03-30 00:04) [15]


> размер приложения в процессе работы растет

Где-то утечка памяти.


 
Незнайка Винидиктович   (2009-03-30 00:12) [16]


> > Я хотел бы обратить внимание, что он всегда передает указатель
> > на одну и ту же переменную, которую потом перезаписывает
> > при каждом новом коннекте.Где там указатель? Там приведение
> типа SOCKET к типу Pointer. Никакого указателя там нет.И
> ничего он не перезаписывает. Внимательно на код посмотрите.
>

Совершенно верно


 
Незнайка Винидиктович   (2009-03-30 00:17) [17]


> > размер приложения в процессе работы растетГде-то утечка
> памяти.

Извините конечно за глупость, но как её искать? )


 
DVM ©   (2009-03-30 00:19) [18]


> мимо   (30.03.09 00:04) [14]


> Где там указатель? Там приведение типа SOCKET к типу Pointer.
>  Никакого указателя там нет.

Да все верно, че-то я перепутал. Мне почему то казалось что там написано типа такого: pointer(@accepted_sock)

Уж не знаю, с чего я так решил.


 
DVM ©   (2009-03-30 00:22) [19]


> размер приложения в процессе работы растет

Не факт, что утечка, где смотрите размер занимаемой памяти? В диспетчере задач? Если да, то в каком столбце? Лучше взять что-то вроде MemProof и смотреть там, покажет все утечки вплоть до строк в коде (если его правильно настроить)


 
Незнайка Винидиктович   (2009-03-30 00:33) [20]


> Не факт, что утечка, где смотрите размер занимаемой памяти?
>  В диспетчере задач? Если да, то в каком столбце? Лучше
> взять что-то вроде MemProof и смотреть там, покажет все
> утечки вплоть до строк в коде (если его правильно настроить)

Да в диспетчере задач. смотрю в колонку память ) Предложенный софт сейчас попробую, может что выйде из этого


 
Незнайка Винидиктович   (2009-03-30 00:49) [21]

MemProof тоже показывает утечку, т.е. текущие и пиковые значения примерно равны... но как найти утечку пока не понял, вообщем в процессе поиска ))


 
DVM ©   (2009-03-30 00:53) [22]


> Да в диспетчере задач. смотрю в колонку память )

Смотри Виртуальную память, но все равно это не точно и неудобно, лучше использовать спец инструменты.


 
DVM ©   (2009-03-30 00:55) [23]


> Незнайка Винидиктович   (30.03.09 00:49) [21]

Можно для начала воспользоваться не MemProof, а FastMM4.


 
мимо   (2009-03-30 01:48) [24]

Ну можно вообще просто считать вызовы GetMem/FreeMem (переопределить указатели на эти функции - это самое простое).


 
Германн ©   (2009-03-30 02:10) [25]


> мимо   (30.03.09 01:48) [24]
>
> Ну можно вообще просто считать вызовы GetMem/FreeMem (переопределить
> указатели на эти функции - это самое простое).
>

Хм. Это уже мания,
Имхо. :)


 
Сергей М. ©   (2009-03-30 08:22) [26]


> в представленом мной коде всего 13 строк


А никто и не говорил что проблема в представленном коде.
Проблема - в одной из 17-х строк в коде , который ты не представил.


 
Незнайка Винидиктович   (2009-03-30 08:43) [27]


> > в представленом мной коде всего 13 строкА никто и не говорил
> что проблема в представленном коде.Проблема - в одной из
> 17-х строк в коде , который ты не представил.

безусловно это так, но весь код немогу вставить тут ограничение )) ну вообщемто проблема сейчас уже в другом (


 
Незнайка Винидиктович   (2009-03-30 08:44) [28]


> Ну можно вообще просто считать вызовы GetMem/FreeMem (переопределить
> указатели на эти функции - это самое простое).

Так я вообще в своем приложении использовал только переменные интеджер и стринг впринципе...


 
Сергей М. ©   (2009-03-30 08:48) [29]


> весь код немогу вставить


Не надо ничего никуда "вставлять".
Потенциальный источник проблем :

> никакой синхронизации нету(за её ненадобностью)


Флаг IsMultiThread имеет прямое отношение к синхронизации.


 
Сергей М. ©   (2009-03-30 08:53) [30]


> использовал .. стринг


Ну вот тебе и грабли, как и просил)


 
Незнайка Винидиктович   (2009-03-30 08:57) [31]


> > весь код немогу вставитьНе надо ничего никуда "вставлять".
> Потенциальный источник проблем :> никакой синхронизации
> нету(за её ненадобностью)Флаг IsMultiThread имеет прямое
> отношение к синхронизации.

Как я понимаю(при моём скромном опыте программирования), что синхронизация нужна только в том случае если потоки обращаютсья одновременно к общим ресурсам, так?


 
Сергей М. ©   (2009-03-30 09:34) [32]

Так.
Ресурсы BMM (Borland Memory Manager в составе Run-Time Library) как раз и есть общие.
Работая с длинными строками ты неявно обращаешься к BMM и, соотв-но, к его ресурсам.
Установка глобального флага IsMultiThread предписывает BMM при помощи крит.секции выстраивать в очередь явные или неявные запросы к нему со стороны потоков прикладного кода, это и есть та самая синхронизация, в которой у тебя якобы нет необходимости.
Этот же флаг неявно взводится при вызове BeginThread, кр.того BeginThread делает еще несколько крайне полезных действий, направленных, например, на корректную и удобную обработку неперехваченных тобой исключений, потенциально могущих возникать в теле поточной функции.


 
Незнайка Винидиктович   (2009-03-30 09:38) [33]


> Так.Ресурсы BMM (Borland Memory Manager в составе Run-Time
> Library) как раз и есть общие.Работая с длинными строками
> ты неявно обращаешься к BMM и, соотв-но, к его ресурсам.
> Установка глобального флага IsMultiThread предписывает BMM
> при помощи крит.секции выстраивать в очередь явные или неявные
> запросы к нему со стороны потоков прикладного кода, это
> и есть та самая синхронизация, в которой у тебя якобы нет
> необходимости.

Немного в шоке оО
Т.е. даже если эта строка локальная в поточной функции с помощью какого-то BMM евляеться общей ??
нет я даже много в шоке )


 
Незнайка Винидиктович   (2009-03-30 09:41) [34]

Ну впринципе сейчас попробую переделать на БегинТред, посмотрим что из этого выйдет.


 
Незнайка Винидиктович   (2009-03-30 09:48) [35]

хм. в BeginThread заголовок вроде идентичен с CreateThread, а вот параметр для функции некорректно воспринимает


 
Сергей М. ©   (2009-03-30 10:11) [36]


> строка локальная в поточной функции с помощью какого-то
> BMM евляеться общей ?


Да не строка общая, а ресурсы самого BMM !
Обращение к этим ресурсам происходит в момент неявных вызовов Get/Realloc/FreeMem, потенциально происходящих при использовании длинных строк. Причем фиолетово, локальные ли эти строковые переменные или не локальные.


 
Сергей М. ©   (2009-03-30 10:12) [37]


> параметр для функции некорректно воспринимает


Читай текст ошибки, вникай, исправляй ошибку


 
Незнайка Винидиктович   (2009-03-30 10:17) [38]


> > параметр для функции некорректно воспринимаетЧитай текст
> ошибки, вникай, исправляй ошибку

Да ошибки то как таковой нету, просто значения в поток передаеться вместо одного другое (( хотя все по мануалу делаю (


 
Незнайка Винидиктович   (2009-03-30 10:21) [39]

     accepted_sock:=Accept(srv_sock,@Addr,@addr_size);
     BeginThread(nil, 0, @cli_thread, pointer(accepted_sock), 0, h);


а в потоке так:

procedure cli_thread(param: pointer); stdcall;
var
       cli_sock: integer;
       ......
begin
       cli_sock:=integer(param);
       ......


так вот работало с CreateThread. с бегинтред нихочет, даже делал по ману через указатель и передачу адреса, всеравно нето (


 
Незнайка Винидиктович   (2009-03-30 10:22) [40]

т.е. в cli_sock нето значение получаеться



Страницы: 1 2 3 вся ветка

Форум: "Начинающим";
Текущий архив: 2009.05.24;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.006 c
4-1197823589
MetalFan
2007-12-16 19:46
2009.05.24
ReadFile c Overlapped, ньюансы работы.


2-1239101143
SkyN
2009-04-07 14:45
2009.05.24
почему OnIdle перестает вызываться


15-1237488048
KSergey
2009-03-19 21:40
2009.05.24
Запуск программы под другой уетной записью


2-1239200285
NormaN
2009-04-08 18:18
2009.05.24
Как создать копию файла *.mdb с выбранными записями?


15-1237300022
@!!ex
2009-03-17 17:27
2009.05.24
Помогите с webmoney





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский