Вызвано исключение по адресу 0x0000000000000000 в ...

Created on: August 29, 2025

Answered using GPT-5 Thinking by Chat01

Question

Вызвано исключение по адресу 0x0000000000000000 в TEST_AGP.exe: 0xC0000005: нарушение прав доступа при исполнении по адресу 0x0000000000000000. - я получаю эту ошибку при использовании своей функции из своей DLL причём я точно знаю что сама библиотека загружается я это уже проверил и отладил сама библиотека загружается 100 процентов, extern "C++" __declspec(dllexport) __declspec(noalias)std::vector<float> Base_LNA_1_2_Mer_AGP(const uint32_t N,
const uint32_t global_iterations, const float a, const float b, const float c, const float d, const float r,
const bool mode, const float epsilon, const uint32_t seed) noexcept
{ - вот так выглядит объявление моей функции в DLL, а вот так эта функция вызывается в основном приложении: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
chart2->Series[0]->Points->Clear();
chart2->Series[1]->Points->Clear();
chart2->Series[2]->Points->Clear();
chart2->Series[3]->Points->Clear();

text
static LARGE_INTEGER start, end; QueryPerformanceCounter(&start); const uint32_t seed = GetTickCount(); HINSTANCE load_function = LoadLibrary(L"TEST_FUNC.dll"); typedef std::vector<float>(*agp)(const uint32_t, const uint32_t, const float, const float, const float, const float, const float, const bool, const float, const uint32_t); agp Base_LNA_1_2_Mer_AGP = (agp)GetProcAddress(load_function, "Base_LNA_1_2_Mer_AGP"); const std::vector<float> Extr_2D = Base_LNA_1_2_Mer_AGP(2, 10000, -2.2f, 1.8f, -2.2f, 1.8f, 2.5f, false, 0.0001f, seed); const std::vector<float> Extr_2D_LNA = Base_LNA_1_2_Mer_AGP(2, 10000, -2.2f, 1.8f, -2.2f, 1.8f, 2.5f, true, 0.0001f, seed); FreeLibrary(load_function); QueryPerformanceCounter(&end); LARGE_INTEGER freq; QueryPerformanceFrequency(&freq); const uint32_t multiplier = ((1ULL << 32) / freq.QuadPart) * 1'000'000ULL; textBox5->Text = Convert::ToString( ((end.QuadPart - start.QuadPart) * multiplier) >> 32 ) + " microseconds"; textBox2->Text = Convert::ToString(Extr_2D.back()); textBox1->Text = Convert::ToString(Extr_2D_LNA.back()); } - тут всё должно быть корректно я это также проверил, причём эта ошибка возникает именно в этой строчке const std::vector<float> Extr_2D = Base_LNA_1_2_Mer_AGP(2, 10000, -2.2f, 1.8f, -2.2f, 1.8f, 2.5f, false, 0.0001f, seed); сразу после знака равно

Thought

Evaluating export approach

I'm considering the best way to export a function safely. Options include using __declspec(dllexport) with extern "C" for compatibility, or using a custom allocator for returning a std::vector<float>. Another thing to check is whether a function pointer is null due to wrong calling conventions or GetProcAddress returning NULL.

Checking function pointer

I need to verify that GetProcAddress successfully returns the function pointer for Base_LNA_1_2_Mer_AGP. If it doesn’t work, I should check for errors using GetLastError(). Additionally, I’m considering using extern "C" and __declspec(dllexport) for simpler native calling. There could be a .NET/CLI environment issue too.

Considering linking conventions

The library and the caller are both compiled by MSVC, but using GetProcAddress bypasses type checking, leaving room for possible mismatched calling conventions (like __vectorcall or __fastcall). To avoid issues, I should use extern "C" to prevent name mangling, instead of extern "C++".

Fixing linkage issues

It appears they might have meant to write extern "C", but accidentally wrote extern "C++". Using extern "C++" causes name mangling, which would break GetProcAddress. I could suggest extern "C" with __declspec(dllexport) for simpler exports, but std::vector types can’t usually be exported with C linkage.

Addressing export and memory issues

It looks like using extern "C" is necessary for proper linking, especially when GetProcAddress is involved. However, you can’t use std::vector with C linkage due to type compatibility issues. The immediate fix is to use a wrapper function with C-compatible types for exporting, and either rely on import libraries or function decoration. Pay attention to memory allocation mismatches and potential issues with destructors and memory freeing across DLL boundaries.

Analyzing linkage and memory issues

The crash seems to happen because of a null pointer call, likely caused by name mangling when using GetProcAddress with a C++ function. To resolve, ensure that you're exporting functions with plain types or via a C wrapper. Do not return std::vector between DLL and application, as this can cause ABI instability and heap corruption. Avoid GetProcAddress for C++ functions with STL returns—use import libraries or C wrappers instead.

Thought for 1m 21s

Answer

Коротко: вы почти наверняка вызываете нулевой указатель функции. Адрес выполнения 0x0000000000000000 при 0xC0000005 означает, что GetProcAddress(...) вернул nullptr, а вы всё равно сделали вызов.

Почему так случилось

  1. У вас экспорт объявлен как extern "C++" ... Base_LNA_1_2_Mer_AGP(...).
    С C++-линковкой имя заманглировано, а вы ищете в DLL строку "Base_LNA_1_2_Mer_AGP". В результате GetProcAddress не находит символ.

  2. Даже если бы нашли, возвращать/принимать std::vector<float> через границу DLL небезопасно (разные версии CRT/компилятора/аллокатора ⇒ краши при копировании/деструкции, особенно после FreeLibrary).

Что сделать прямо сейчас

  • Добавьте проверку результата GetProcAddress и выведите GetLastError() — вы сразу увидите, что указатель нулевой:
cpp
auto proc = (agp)GetProcAddress(load_function, "Base_LNA_1_2_Mer_AGP"); if (!proc) { DWORD e = GetLastError(); MessageBox::Show("GetProcAddress failed: " + e.ToString()); FreeLibrary(load_function); return; }

Надёжные варианты исправления

Вариант A (правильный): C-обёртка + простые типы

Экспортируйте C-функцию (без манглинга), которая возвращает данные через буфер/длину. Саму “умную” C++ функцию оставьте внутренней.

В DLL:

cpp
// внутренняя C++ функция (как у вас сейчас) static std::vector<float> Base_LNA_1_2_Mer_AGP_cpp(uint32_t N, uint32_t global_iterations, float a,float b,float c,float d,float r, bool mode, float epsilon, uint32_t seed) noexcept; // C-обёртка: без std::vector в сигнатуре! extern "C" __declspec(dllexport) int __cdecl Base_LNA_1_2_Mer_AGP_C( uint32_t N, uint32_t global_iterations, float a,float b,float c,float d,float r, bool mode, float epsilon, uint32_t seed, float** out_data, uint32_t* out_len) { try { auto v = Base_LNA_1_2_Mer_AGP_cpp(N,global_iterations,a,b,c,d,r,mode,epsilon,seed); *out_len = (uint32_t)v.size(); *out_data = (float*)CoTaskMemAlloc(sizeof(float) * (*out_len)); if (!*out_data) return 2; // OOM memcpy(*out_data, v.data(), sizeof(float) * (*out_len)); return 0; // ok } catch(...) { return 1; } // ошибка } extern "C" __declspec(dllexport) void __cdecl Base_LNA_1_2_Mer_AGP_Free(float* p) { CoTaskMemFree(p); }

В EXE:

cpp
typedef int (__cdecl *agp_c)( uint32_t,uint32_t,float,float,float,float,float,bool,float,uint32_t, float** ,uint32_t*); typedef void (__cdecl *agp_free)(float*); HINSTANCE h = LoadLibrary(L"TEST_FUNC.dll"); auto f = (agp_c) GetProcAddress(h, "Base_LNA_1_2_Mer_AGP_C"); auto ffree= (agp_free)GetProcAddress(h, "Base_LNA_1_2_Mer_AGP_Free"); if (!f || !ffree) { /* обработать ошибку */ } float* buf=nullptr; uint32_t len=0; int rc = f(2,10000,-2.2f,1.8f,-2.2f,1.8f,2.5f,false,0.0001f,seed,&buf,&len); if (rc==0) { std::vector<float> Extr_2D(buf, buf+len); ffree(buf); // ... используете Extr_2D } FreeLibrary(h);

Плюсы: стабильные имена (extern "C"), нет передачи STL через границу модуля, нет зависимости от версии компилятора/CRT.

Вариант B (временный/не рекомендую на долгую перспективу)

Оставить C++ сигнатуру, но:

  • экспортировать через .def файл с алиасом неманглированного имени;
  • или вызывать GetProcAddress по могласному имени (узнать через dumpbin /exports TEST_FUNC.dll);
  • и обязательно собрать DLL и EXE одной версией MSVC с /MD (общий CRT).
    Даже так это хрупко: std::vector через DLL — источник тонких падений.

Мелочи, на которые стоит взглянуть

  • Сделайте явным соглашение о вызовах: __cdecl и в DLL, и в typedef.
  • Не вызывайте функцию, не проверив указатель — всегда проверяйте GetProcAddress.
  • Не делайте FreeLibrary до тех пор, пока не закончите работу со всеми буферами, которые освобождаются функциями из DLL (в варианте A — вызвать *_Free до FreeLibrary).

Итог

  • Текущая авария — из-за того, что вы зовёте nullptr (из-за C++-мэнглинга).
  • Даже после починки экспорта лучше перейти на C-обёртку с float**/len и отдельной функцией освобождения — это снимет класс проблем со std::vector через границу DLL.

Share this Q&A