2015-07-21 2 views
0

Я хотел бы сообщить, что я относительно новичок в C++ (и чувствую себя немного виноватым, задавая два вопроса в тот же день, относящийся к тому же проекту).Исполняемый сбой после функции вызова Thrice


Запуск цикла ниже (или раскомментировав пять последовательных линий, требующие MyDownloadFunction затем работает), вызовет сбой приложения. Сообщение

Ошибка:
terminate called after throwing an instance of 'std::ios_base::failure' what(): basic_ios::clear This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information.

То, что я хотел бы знать, почему он не откажет, если функция вызывается только один раз или два раза, но падает, если он запускается 3 или более раз (а в третий раз файл сохраняется правильно) и, конечно же, как его исправить.

Пожалуйста, примите во внимание, что https://MyWebsite.com существует по этому вопросу.

#include <iostream> 
#include <sstream> 
// #include <stdio.h> 
// #include <string> 
#include <windows.h> 

using namespace std; 

int main() { 
    typedef int * (*MyDownloadToUrl)(void*, const char*, const char*, DWORD, void*); 
    HINSTANCE LibHnd = LoadLibrary("Urlmon.dll"); 
    MyDownloadToUrl MyDownloadFunction = (MyDownloadToUrl)GetProcAddress(LibHnd,"URLDownloadToFileA"); 

    stringstream URL; 
    stringstream Iteration; 

    // MyDownloadFunction(NULL, "https://google.ca", "Google 1.htm", 0, NULL); 
    // MyDownloadFunction(NULL, "https://google.ca", "Google 2.htm", 0, NULL); 
    // MyDownloadFunction(NULL, "https://google.ca", "Google 3.htm", 0, NULL); 
    // MyDownloadFunction(NULL, "https://google.ca", "Google 4.htm", 0, NULL); 
    // MyDownloadFunction(NULL, "https://google.ca", "Google 5.htm", 0, NULL); 

    for (int i = 1; i <= 5; i++) { 
     URL << "https://MyWebsite.com/" << i << "/"; 
     cout << URL.str() << "\r\n"; 

     Iteration << i << ".htm"; 
     cout << Iteration.str() << "\r\n\r\n"; 

     MyDownloadFunction(NULL, URL.str().c_str(), Iteration.str().c_str(), 0, NULL); 

     URL.str(""); 
     Iteration.str(""); 
    } 
} 

ответ

1

URLDownloadToFile (и большинство, если не все другие функции API Windows) использует STDCALL соглашение о вызове, а не ccall конвенции. Также первый и последний параметры не являются void* s, они равны LPUNKNOWN и LPBINDSTATUSCALLBACK, и он возвращает HRESULT, а не int*. Неопределенное поведение вызывает функцию одного типа с помощью указателя на другой тип. Поэтому вам нужно изменить свой typedef на:

typedef HRESULT (__stdcall *MyDownloadToUrl)(LPUNKNOWN, const char*, const char*, DWORD, LPBINDSTATUSCALLBACK); 
+0

Изменение 'typedef' на указанную вами линию вызывает множество проблем с компилятором. Кроме того, насколько я понимаю, 'NULL' может быть передан в' void * 'без проблем (в документации он говорит нам использовать' NULL', когда не требуется статус загрузки). –

+0

Истинное использование 'void *' возможно, возможно, ОК, но это неопределенное поведение. Он может работать идеально, или он может переформатировать ваш жесткий диск. Язык не дает никаких гарантий того, что произойдет при вызове UB. Этот typedef работает для меня с помощью Visual Studio 2010. Я не использовал mingw много, но похоже, что вам, возможно, придется использовать '__stdcall' вместо' _stdcall'. –

Смежные вопросы