ошибка на InternetReadFile
От: Hare76  
Дата: 07.04.12 05:15
Оценка:
Необходимо скачать файл из интернета... достаточно большой (от нескольких десятков мегабайт и выше) по HTTP протоколу. Проблема в том, что если его сразу в буфер целиком закачивать, то все проходит гладко. Но мне надо его закачивать частями, так как не факт, что буфер достаточно большого размера будет выделен на другой машине. Так вот частями он закачивается, только если перед обращениями к InternetReadFile поставить небольшую паузу на треть секунды (или в дебагере пошагово тоже работает). А в реальном времени вылетает с ошибкой сегментации (Access violation). В чем может быть проблема? Может кто сталкивался?
internetreadfile
Re: ошибка на InternetReadFile
От: okman Беларусь https://searchinform.ru/
Дата: 07.04.12 09:32
Оценка:
Здравствуйте, Hare76, Вы писали:

H>Необходимо скачать файл из интернета... достаточно большой (от нескольких десятков мегабайт и выше) по HTTP протоколу. Проблема в том, что если его сразу в буфер целиком закачивать, то все проходит гладко. Но мне надо его закачивать частями, так как не факт, что буфер достаточно большого размера будет выделен на другой машине. Так вот частями он закачивается, только если перед обращениями к InternetReadFile поставить небольшую паузу на треть секунды (или в дебагере пошагово тоже работает). А в реальном времени вылетает с ошибкой сегментации (Access violation). В чем может быть проблема? Может кто сталкивался?


Покажите код, там будет видно.
Скорее всего, неправильно используются функции WinInet.
Re[2]: ошибка на InternetReadFile
От: Hare76  
Дата: 07.04.12 09:46
Оценка:
Здравствуйте, okman, Вы писали:

O>Здравствуйте, Hare76, Вы писали:


H>>Необходимо скачать файл из интернета... достаточно большой (от нескольких десятков мегабайт и выше) по HTTP протоколу. Проблема в том, что если его сразу в буфер целиком закачивать, то все проходит гладко. Но мне надо его закачивать частями, так как не факт, что буфер достаточно большого размера будет выделен на другой машине. Так вот частями он закачивается, только если перед обращениями к InternetReadFile поставить небольшую паузу на треть секунды (или в дебагере пошагово тоже работает). А в реальном времени вылетает с ошибкой сегментации (Access violation). В чем может быть проблема? Может кто сталкивался?


O>Покажите код, там будет видно.

O>Скорее всего, неправильно используются функции WinInet.

Код примерно такой (убрал все проверки на ошибки, закрытия функций и т.п.)


#include <windows.h>
#include <wininet.h>
#pragma comment (lib, "wininet.lib")

int main(void)
{

    char* lpszAgent = "wini";
    HINTERNET hInternet;

    hInternet = InternetOpen((LPCWSTR)lpszAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);


    HINTERNET hConnect;
    hConnect=InternetConnect(hInternet, TEXT("obod.by"), INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);



    HINTERNET hRequest;
    hRequest = HttpOpenRequest (hConnect, TEXT("GET"), TEXT("images\/shot_049.jpg"), NULL, NULL, 0, INTERNET_FLAG_PRAGMA_NOCACHE|INTERNET_FLAG_RELOAD,1);

    BOOL bSend=HttpSendRequest(hRequest, NULL, 0, NULL, 0);
    
    DWORD dwBuffer=0;
    DWORD dwBufferLength=4;
    BOOL bInfo= HttpQueryInfo(hRequest, HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER, &dwBuffer, &dwBufferLength, NULL);


    ULARGE_INTEGER FreeBytesAvailable;
    ULARGE_INTEGER TotalNumberOfBytes;
    ULARGE_INTEGER TotalNumberOfFreeBytes;
    BOOL bFreeSpace = GetDiskFreeSpaceEx(NULL, &FreeBytesAvailable, &TotalNumberOfBytes, &TotalNumberOfFreeBytes);


    HANDLE hFile;

    hFile=CreateFile(TEXT("FileName.jpg"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED/*|FILE_FLAG_NO_BUFFERING*/, NULL);
    
    OVERLAPPED ovl;
    ovl.hEvent=NULL;
    ovl.Internal=0;
    ovl.InternalHigh=0;
    ovl.Offset=0;
    ovl.OffsetHigh=0;
    ovl.Pointer=NULL;

    
    SYSTEM_INFO SystemInfo;
    GetSystemInfo(&SystemInfo);

    HANDLE hHeap=HeapCreate(0, 0,0);
    LPVOID Buffer=HeapAlloc(hHeap, HEAP_ZERO_MEMORY, SystemInfo.dwPageSize);
    
    DWORD dwAllReadBytes=0;
    DWORD dwNumberOfBytesRead=0;
    BOOL bIReadFile=1;

            
            
    for(DWORD i=0; i<dwBuffer; i=i+SystemInfo.dwPageSize)
    {
        bIReadFile=InternetReadFile(hRequest, Buffer, SystemInfo.dwPageSize, &dwNumberOfBytesRead);
        BOOL bWriteFile=WriteFileEx(hFile, Buffer,dwNumberOfBytesRead, &ovl, NULL);
        ovl.Offset+=dwNumberOfBytesRead;
    }
            
    return 0;
}
Re[3]: ошибка на InternetReadFile
От: okman Беларусь https://searchinform.ru/
Дата: 07.04.12 10:34
Оценка: 4 (2)
Здравствуйте, Hare76, Вы писали:

H>Код примерно такой (убрал все проверки на ошибки, закрытия функций и т.п.)


Похоже, ошибка вот в этом месте:

        
    for(DWORD i=0; i<dwBuffer; i=i+SystemInfo.dwPageSize)
    {
        bIReadFile=InternetReadFile(hRequest, Buffer, SystemInfo.dwPageSize, &dwNumberOfBytesRead);
        BOOL bWriteFile=WriteFileEx(hFile, Buffer,dwNumberOfBytesRead, &ovl, NULL);
        ovl.Offset+=dwNumberOfBytesRead;
    }        
    return 0;
}


Суть вот в чем — пока выполняется асинхронная операция ввода-вывода (WriteFileEx в данном случае),
структуру OVERLAPPED нельзя трогать.

MSDN:

The OVERLAPPED data structure must remain valid for the duration of the write operation. It should not be a variable that can go out of scope while the write operation is pending completion.


Здесь же она используется в последующих итерациях цикла,
что является известной ошибкой. Выход такой — либо дождаться завершения WriteFileEx, либо
использовать синхронный ввод-вывод.
Re[3]: ошибка на InternetReadFile
От: okman Беларусь https://searchinform.ru/
Дата: 07.04.12 10:36
Оценка:
Здравствуйте, Hare76, Вы писали:

H>>>Так вот частями он [файл] закачивается, только если перед обращениями к InternetReadFile поставить небольшую паузу на треть секунды (или в дебагере пошагово тоже работает). А в реальном времени вылетает с ошибкой сегментации (Access violation).


Потому что пока цикл выполняется медленно или в пошаговом режиме, WriteFileEx успевает отработать.
А в реальном времени исполнения — не успевает.
Re[4]: ошибка на InternetReadFile
От: Hare76  
Дата: 07.04.12 10:47
Оценка:
Здравствуйте, okman, Вы писали:

O>Здравствуйте, Hare76, Вы писали:


H>>Код примерно такой (убрал все проверки на ошибки, закрытия функций и т.п.)


O>Похоже, ошибка вот в этом месте:


O>
        
O>    for(DWORD i=0; i<dwBuffer; i=i+SystemInfo.dwPageSize)
O>    {
O>        bIReadFile=InternetReadFile(hRequest, Buffer, SystemInfo.dwPageSize, &dwNumberOfBytesRead);
O>        BOOL bWriteFile=WriteFileEx(hFile, Buffer,dwNumberOfBytesRead, &ovl, NULL);
O>        ovl.Offset+=dwNumberOfBytesRead;
O>    }        
O>    return 0;
O>}
O>


O>Суть вот в чем — пока выполняется асинхронная операция ввода-вывода (WriteFileEx в данном случае),

O>структуру OVERLAPPED нельзя трогать.

O>MSDN:

O>The OVERLAPPED data structure must remain valid for the duration of the write operation. It should not be a variable that can go out of scope while the write operation is pending completion.


O>Здесь же она используется в последующих итерациях цикла,

O>что является известной ошибкой. Выход такой — либо дождаться завершения WriteFileEx, либо
O>использовать синхронный ввод-вывод.

Спасибо! Помогло! Как-то даже не подумал...
С меня плюсики
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.