VirtualAlloc() и многопоточность
З.Ы. Язык C (не C++)
Код:
поток:
{
SOCKET s = 0;
int rcv_size, snd_size, sz = sizeof(int);
long ptr = 0, bytesRead = 0, p_size = MAX_BUF;
char counter[10];
char substring[MAX_STR];
void *szPage, *recv_str, *send_str;
int exp_count = 0;
int ovector[VECT_SIZE];
int matches = 0;
int i = 0,j = 0;
getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&rcv_size, &sz);
getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&snd_size, &sz);
[COLOR="Red"] if ((recv_str = VirtualAlloc(NULL, rcv_size, MEM_COMMIT, PAGE_READWRITE)) == NULL)
error(10);
if ((send_str = VirtualAlloc(NULL, snd_size, MEM_COMMIT, PAGE_READWRITE)) == NULL)
error(10);
if ((szPage = VirtualAlloc(NULL, MAX_BUF, MEM_COMMIT, PAGE_READWRITE)) == NULL)
error(10);[/COLOR]
for (j=startCount; j<=stopCount; j++) {
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
connect(s, (SOCKADDR*)&sin_remote, sizeof(sin_remote));
memset(send_str, 0, snd_size);
strcpy(send_str, "GET http://");
strcat(send_str, host);
sprintf(counter, "%d", j);
strcat(send_str, substr(query, "{ID}",counter));
strcat(send_str, " HTTP/1.0\nHost: ");
strcat(send_str, host);
strcat(send_str, "\nUser-Agent: ");
strcat(send_str, agent);
strcat(send_str, "\nAccept: */*\nAccept-Language: en-US\n\n\n");
send(s, send_str, (int)strlen(send_str)-1, 0);
p_size = rcv_size;
memset(szPage, 0, MAX_BUF);
while (1) {
memset(recv_str, 0, rcv_size);
if ((bytesRead = recv(s, recv_str, rcv_size, 0)) <= 0)
break;
ptr += bytesRead;
strcat(szPage, recv_str);
}
matches = pcre_exec(re, NULL, (char*)szPage, ptr, 0, 0, ovector, 300);
for (i=0; i<=matches; i++) {
memset(substring, 0, MAX_STR);
pcre_copy_substring((char*)szPage, ovector, matches, i, substring, MAX_STR);
fputs(substring, out);
}
closesocket(s);
}
VirtualFree(recv_str, rcv_size, MEM_DECOMMIT);
VirtualFree(send_str, snd_size, MEM_DECOMMIT);
VirtualFree(szPage, MAX_BUF, MEM_DECOMMIT);
}
вызов из программы:
if ((gmem = VirtualAlloc(NULL, MAX_ALLOC, MEM_RESERVE, PAGE_READWRITE)) == NULL) {
puts("FAILED");
error(-1);
}
puts("SUCCESS");
_beginthread((void*)thread, 0, NULL); // здесь вызываю поток (по рекомендациям авторитетных программистов использую _beginthread вместо API CreateThread()
for (tid=0; tid<=100000; tid++) // здесь жду выполнения потока
{
printf(".");
}
[COLOR=SeaGreen]// thread(); если делаю вот так, то все работает, если выполняю код выше, память не выделяется[/COLOR]
printf("Now trying to release memory...");
if (!(VirtualFree(gmem, 0, MEM_RELEASE))) {
puts("FAILED");
error(-1);
}
puts("SUCCESS");
Т.к. требуемый протокол - Http, я использую в качестве буфера указатель на память,
Указатель в качестве буфера - это сильно!
а саму память выделяю с помощью VirtualAlloc().
Тоже из-за HTTP? А какая связь?
Память должна выделяться в каждом потоке, поэтому перед входом в поток (из основной программы) я вызываю VirtualAlloc() с флагом MEM_RESERVE (т.е. резервирую память, в моем слуае - 20мб), а в самих потоках уже VirtualAlloc с флагом MEM_COMMIT.
Советую почитать документацию (например MSDN) и задуматься:
Зачем вообще нужен MEM_RESERV и нафига он тебе?
Как работает MEM_COMMIT и нафига он тебе нужен отдельно от MEM_RESERV ?
Да и зачем тебе вообще нужен VirtualAlloc, чем malloc не угодил?
Все бы хорошо, но! Когда я создаю поток, VirutalAlloc возвращает NULL!
А код ошибки посмотреть рука не поднимается?
Подскажите, как решить проблему.
Используй malloc, пока не научишься пользоваться VirtualAlloc.
Я так подозреваю, что это возможно особенность архитектуры Windows,
VirtualAlloc - это функция Win32 API.
но материалов про это в сети не нашел.
MSDN
FirsSteps.ru
и ещё сотни сайтов, доступных по ссылке:
http://www.google.ru/search?complete=1&hl=ru&newwindow=1&rlz=1B3GGGL_ruRU213RU213&q=VirtualAlloc&btnG=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA&lr=&aq=-1&oq=
Зачем сразу грешить на функцию? Может, ты её просто готовить не умеешь?
Какие были глюки?
Так что malloc не подходит. А про MEM_RESERVE - http://www.developing.ru/com/virtual_memory_04.html, руководствуясь этой статьей я и реализовал работу с памятью. Уж не знаю что тут такого противоестественного (MEM_COMMIT MEM_RESERVE).
Подумай, как по-твоему вызов с MEM_COMMIT "поймет", что ты имеешь в виду ту область, которую зарезервировал с помощью MEM_RESERVE ?
И непонятно, зачем ты сначала резервируешь память, а потом её коммитишь отдельно в каждом потоке? А если учесть что несколько потоков захотят использовать твою зарезервированную память, как они её будут делить?
Почему бы, если уж не хочешь использовать malloc, не использовать в потоках MEM_RESERVE|MEM_COMMIT ?
здесь 3-й вариант
Ну в файл пиши этот промежуточный буфер
ЗЫ: при чем тут консольное или нет?
Может быть у вас malloc не является потокобезопасной и имеет смысл вокруг не семафор развернуть?
ЗЫ: при чем тут консольное или нет?
Думал об этом, да это выход, но не решение проблемы :) Ведь браузеры как то загружают страницы переменной длины?
причем они не выделяют сразу по 20 метров под него
{
...
if ((recv_str = ()char *malloc(rcv_size)) == NULL)
error(10);
...
free( recv_str );
}
int main()
{
...
HANDLE thr;
thr = CreateThread(NULL, 0, thread, NULL, 0, NULL);
WaitForSingleObject(thr, 40000);
...
}
error 8 = ERROR_NOT_ENOUGH_MEMORY, так что доMEM_RESERVEился
убери вообще MEM_RESERVE и RELEASE из основной функции, поставь MEM_RELEASE вместо DECOMMIT в поток. Попробуй