Может ли повреждение кучи быть вызвано проблемами со связыванием?

#c #access-violation #heap-corruption

#c #нарушение доступа #повреждение кучи

Вопрос:

Я получаю нарушение доступа в своей программе при запуске некоторого кода, который принадлежит библиотеке. Моя программа статически ссылается на библиотеку. Я могу запускать этот код в других проектах без проблем, но по какой-то причине он вылетает в моей программе. Я поместил код в самое начало программы, чтобы убедиться, что никакой другой код не был выполнен, и он все равно вылетает. Я не думаю, что это проблема с библиотекой, поскольку она отлично работает в других контекстах. Я понятия не имею, почему происходит сбой, и я пытаюсь выяснить это уже две недели. Вот более подробный пост, который я скопировал на страницу библиотеки github:

Я пытаюсь использовать http_listener в проекте MFC, созданном в Visual Studio 2017 с набором инструментов платформы v141. Он работает нормально до тех пор, пока не будет выполнен код, который ссылается на cpprestsdk. cpprestsdk был установлен с помощью vcpkg, который создал cpprestsdk с использованием набора инструментов платформы vc141.

В моем проекте нет известных ранее существовавших проблем с повреждением кучи, поэтому тот факт, что это вызывает повреждение кучи, сбивает с толку.

Вот нарушающая строка кода:

 BOOL CAuthenticationServerApp::InitInstance()
{
    CWinApp::InitInstance();

    utility::string_t port = U("34568");
    utility::string_t address = U("http://127.0.0.1:");
    address.append(port);

    web::uri_builder uri(address);

    auto addr = uri.to_uri().to_string();
---->std::unique_ptr<http_listener> listener = std::make_unique<http_listener>(addr);
    listener->open().wait();
    ...
  

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

Сообщение об ошибке:

Исключение, вызванное 0x005B90F8 в AuthenticationServer.exe: 0xC0000005: место записи с нарушением доступа 0x0B39D000. Возникло необработанное исключение: нарушение доступа на запись.

Вот стек вызовов, в котором генерируется исключение. Происходит сбой при попытке объявить переменную в конструкторе http_listener_impl:

     AuthenticationServer.exe!std::_Ptr_base<Concurrency::details::_Task_impl<unsigned char> >::_Ptr_base<Concurrency::details::_Task_impl<unsigned char> >() Line 1158  C  
    AuthenticationServer.exe!std::shared_ptr<Concurrency::details::_Task_impl<unsigned char> >::shared_ptr<Concurrency::details::_Task_impl<unsigned char> >(void * __formal) Line 1277 C  
    AuthenticationServer.exe!Concurrency::task<unsigned char>::task<unsigned char>() Line 2963  C  
    AuthenticationServer.exe!Concurrency::task<void>::task<void>() Line 3985    C  
    AuthenticationServer.exe!web::http::experimental::listener::details::http_listener_impl::http_listener_impl(web::uri address) Line 58   C  
    AuthenticationServer.exe!utility::details::make_unique<web::http::experimental::listener::details::http_listener_impl,web::uri>(web::uri amp;amp; arg1) Line 389  C  
    AuthenticationServer.exe!web::http::experimental::listener::http_listener::http_listener(web::uri address) Line 222 C  
    [External Code] 
    AuthenticationServer.exe!CAuthenticationServerApp::InitInstance() Line 79   C  
    AuthenticationServer.exe!AfxWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * lpCmdLine, int nCmdShow) Line 37   C  
    AuthenticationServer.exe!WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * lpCmdLine, int nCmdShow) Line 26  C  
    [External Code] 
  

Этот код на самом деле работает нормально, если я помещаю его в новый проект MFC или другой проект MFC аналогичного размера. Возможно ли, что проблема в библиотеке, или это как-то связано с моим кодом? В программе есть некоторые глобальные переменные, которые я проверил, и ни одна из них не содержит кода, который выделяет или освобождает память в куче в их конструкторах. Итак, я не знаю, как повреждается куча. Проект ссылается на несколько других библиотек, и я позаботился о том, чтобы все они были созданы с использованием одного и того же набора инструментов платформы. Библиотеки не имеют известных проблем и используются годами. Я поместил код http_listener в другой проект, который почти идентичен этому, с теми же зависимостями, и он работает нормально.

Комментарии:

1. Можете ли вы рассказать нам о библиотеке, как вы ее вызываете, вашем компоновщике и ваших параметрах / процессе связывания?

2. что ж, вот полная ссылка на проблему. Я опубликовал это на странице github для библиотеки, которую я использую. github.com/Microsoft/cpprestsdk/issues/1092

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

4. Я определенно видел повреждение кучи в результате связывания кода, скомпилированного с версией компилятора A, с объектными файлами или библиотеками, скомпилированными с версией компилятора B. В моем случае это произошло бы, когда код, скомпилированный с версией компилятора A, выделил бы объект, а затем код, скомпилированный с версией компилятора B, позже освободил бы объект (я предполагаю, что некоторые детали реализации кучи памяти, включенные статически, изменились между двумя версиями компилятора). Если у вас есть возможность скомпилировать все из исходного кода (вместо того, чтобы полагаться на предоставленные объектные файлы), я рекомендую это.

5. Если ваш код включает файл заголовка из версии, отличной от версии библиотеки, то это может легко вызвать сбой. Возможно, вы случайно поместили более новый / старый файл заголовка в каталог вашего проекта? Если там есть другое объявление http_listener, то все ставки отменяются