Как отладить проблемы с DLL в MinGW?

При использовании MinGW легко нарваться на DLL-ад, то есть ваша программа не запускается, потому что она либо не находит необходимые библиотеки DLL, либо находит их несовместимые версии.

Это может проявляться как:

  • «Выполнение кода не может быть продолжено, поскольку __.dll не найден».
  • «Точка входа в процедуру __ не найдена в динамической библиотеке __»
  • Приложение не запускается без каких-либо сообщений об ошибках.

Как это исправить?


(This is intended as a canonical duplicate on this topic.)

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
132
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Что означают ошибки?

Для запуска вашей программы требуется несколько .dll («общих библиотек»). Это либо части стандартной библиотеки (поставляемой вместе с вашим компилятором), либо сторонние библиотеки, которые вы используете.

  • «выполнение не может быть продолжено, поскольку __.dll не найден» — необходимый .dll не найден ни в одном из нескольких предопределенных путей поиска (см. ниже).

  • «Точка входа в процедуру… не найдена…» — найдена необходимая .dll, но не правильная ее версия.

    Имя файла в сообщении об ошибке может быть отвлекающим маневром, но это не обязательно библиотека-нарушитель.

  • Приложение не запускается без ошибок — ошибка может не отображаться при запуске с консоли или из IDE. Дважды щелкните файл .exe в проводнике, чтобы увидеть полное сообщение об ошибке, которое будет одним из приведенных выше. (Под «проводником» я имею в виду приложение Windows «Файлы», а не, например, вкладку VSC с тем же именем.)

Где моя программа ищет библиотеки DLL?

Вы можете обратиться к руководству, но краткое описание таково: (поиск происходит в таком порядке)

  • Каталог, в котором находится ваш .exe.

  • C:\Windows и некоторые его подкаталоги. (⚠️ Никогда не изменяйте и не копируйте там ничего!)

  • Каталоги в PATH в том порядке, в котором они перечислены. (PATH — это «переменная среды» (системная настройка), содержащая список каталогов, в которых, помимо прочего, осуществляется поиск DLL).

    Существует две настройки PATH: общесистемная и для каждого пользователя, первая ищется первой.

Как исправить?

Есть несколько вариантов, от самого простого до самого сложного, выбирайте один.

  1. Статическая связь

    Добавьте -static к флагам компоновщика. Это делает вашу программу не зависимой от DLL, встраивая их содержимое в исполняемый файл.

    Почему это нехорошо?

    • Ваши пользователи не смогут легко обновить библиотеки до более новых версий, если им это необходимо.

    • Некоторые библиотеки лицензируются таким образом, что это препятствует. (Например, при использовании лицензии LGPL статическая ссылка требует открытия исходного кода вашего программного обеспечения.)

  2. Запуск из терминала MSYS2 (если вы используете MSYS2)

    Терминал MSYS2 автоматически настраивает свой собственный PATH, чтобы в первую очередь была установлена ​​установка компилятора (который включает в себя библиотеки DLL стандартной библиотеки, с которыми у вас, вероятно, есть проблемы).

    В меню «Пуск» есть несколько ярлыков MSYS2, и вы ДОЛЖНЫ выбрать правильный (обычно UCRT64 или MINGW64, но прочитайте Что такое среды MSYS2? Как мне выбрать одну?, чтобы знать наверняка).

    Хотя это решит вашу проблему, вы не можете ожидать, что ваши пользователи установят MSYS2, поэтому вам следует рассмотреть другие решения в долгосрочной перспективе.

    Если это не помогло, вероятно, вы использовали неправильный ярлык MSYS2. Вы также можете ознакомиться с разделом «Чего не следует делать» ниже, в разделе о мусоре в C:\Windows.

  3. Исправьте свой ПУТЬ

    Измените свой PATH, чтобы включить каталог с DLL. Обычно это каталог установки компилятора (поскольку там находится его стандартная библиотека), например C:\path\to\MinGW\bin (подставьте свой путь). Если вы используете MSYS2, это будет C:\msys64\ucrt64\bin или C:\msys64\mingw64\bin (читайте Что такое среды MSYS2? Как мне выбрать одну?, чтобы узнать, какой каталог выбрать).

    (This only makes sense for the standard library DLLs. For third-party libraries, always copy them next to the executable as explained in (4) below.)

    Этот каталог должен быть первым в PATH. В противном случае вы рискуете получить несовместимые версии одних и тех же DLL из предыдущих каталогов.

    Существует две настройки PATH: общесистемная и индивидуальная для пользователя. Первый имеет приоритет, поэтому используйте общесистемный PATH.

    Хотя это решит вашу проблему, вы не можете ожидать, что ваши пользователи установят MinGW, поэтому вам следует рассмотреть другие решения в долгосрочной перспективе.

    Как мне установить PATH?

    • В настройках введите «env» в поле поиска, нажмите Edit the system environment variables, нажмите Environment Variables... внизу, затем во втором списке под названием System variables дважды щелкните Path, введите свой путь (например, C:\path\to\MinGW\bin) в пустую ячейку внизу, нажмите Move Up несколько раз, чтобы сделать это первой записью, затем нажмите OK во всех открытых диалогах.

    • Не забудьте перезапустить консоль/IDE после изменения PATH!

    Если это не сработало и вы уверены, что все сделали правильно, обратитесь к разделу «Чего не следует делать» ниже, часть о мусоре в C:\Windows.

  4. Скопируйте необходимые библиотеки DLL рядом с исполняемым файлом.

    Копирование DLL — лучшее долгосрочное решение. Вам все равно придется это сделать, чтобы распространять свое приложение среди других (это или статическая ссылка, см. выше). В следующем разделе объясняется, как это сделать.

Какие библиотеки DLL следует скопировать рядом с исполняемым файлом?

Требуемые библиотеки DLL могут быть упомянуты в сообщении об ошибке, но:

  • Вы не можете быть уверены, что список полон.
  • Этот подход не может быть автоматизирован.

Существуют инструменты, которые сообщат вам список DLL, от которых зависит ваше приложение, например. нтлдд. Оно устарело, но выполняет свою работу.

Примечание. Для этого вам необходимо правильно настроить PATH (см. выше; или запустить его в терминале MSYS2, как описано выше), чтобы вы уже могли запускать свое приложение. И нельзя использовать -static.

Пользователи MSYS2 могут установить ntldd с помощью pacman -S ...-ntldd (например, mingw-w64-ucrt-x86_64-ntldd или mingw-w64-x86_64-ntldd, проконсультируйтесь Что такое среды MSYS2? Как мне выбрать одну?). Если вы не используете MSYS2, загрузите его по ссылке GitHub выше.

Беги ntldd -R my_program.exe. Вы увидите длинный список. Игнорируйте все, что не находится в каталоге вашего компилятора (и не является сторонней библиотекой, установленной вами отдельно). В терминале MSYS2 вы можете запустить ntldd -R my_program.exe | grep 'C:\\msys64' для автоматической фильтрации.

В итоге у меня получились libstdc++-6.dll, libgcc_s_seh-1.dll, libwinpthread-1.dll, но ваш список может отличаться в зависимости от типа MinGW, который вы используете.

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

Чего не делать?

  • Не копируйте сторонние библиотеки в свою установку компилятора.

    • Вы можете потерять след того, что скопировали.

    • Если вы используете MSYS2, ваши пользовательские библиотеки могут конфликтовать с тем, что устанавливает менеджер пакетов.

    Вместо этого храните их в отдельном каталоге (используйте -I и -L, чтобы сообщить компилятору, где они находятся) и скопируйте библиотеки DLL рядом с исполняемым файлом.

  • Ничего не копируйте в C:\Windows.

    Некоторые пользователи (или даже установщики) в своей бесконечной мудрости могут скопировать DLL в C:\Windows. Это вызовет проблемы, поскольку этот каталог имеет приоритет над содержимым PATH.

    В общем, если вы видите одну и ту же DLL как в установке компилятора, так и в C:\Windows, это может означать, что последней там не место и ее следует удалить. Но руководствуйтесь здравым смыслом: вы обязаны не сломать свою систему.

Интересно, почему никто никогда не создавал сценарий под названием «пакет», который просто рекурсивно использует ntldd и помещает все в выбранный вами каталог. Я думаю, что чатгпт справится с этим за 1 час.

Rainb 11.06.2024 09:05

@Rainb ntldd уже рекурсивен с флагом -R. Но да, это не должно быть сложно, вам просто нужно отклонить библиотеки в C:\Windows и, возможно, в некоторых других.

HolyBlackCat 11.06.2024 09:12

Другие вопросы по теме