Вызвано исключение по адресу 0x0000000000000000 в ...
Creado el: 29 de agosto de 2025
Respondido usando GPT-5 Thinking por Chat01
Creado el: 29 de agosto de 2025
Respondido usando GPT-5 Thinking por Chat01
Вызвано исключение по адресу 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();
textstatic 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); сразу после знака равно
Коротко: вы почти наверняка вызываете нулевой указатель функции. Адрес выполнения 0x0000000000000000
при 0xC0000005
означает, что GetProcAddress(...)
вернул nullptr
, а вы всё равно сделали вызов.
Почему так случилось
У вас экспорт объявлен как extern "C++" ... Base_LNA_1_2_Mer_AGP(...)
.
С C++-линковкой имя заманглировано, а вы ищете в DLL строку "Base_LNA_1_2_Mer_AGP"
. В результате GetProcAddress
не находит символ.
Даже если бы нашли, возвращать/принимать std::vector<float>
через границу DLL небезопасно (разные версии CRT/компилятора/аллокатора ⇒ краши при копировании/деструкции, особенно после FreeLibrary
).
Что сделать прямо сейчас
GetProcAddress
и выведите GetLastError()
— вы сразу увидите, что указатель нулевой:cppauto 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; }
Надёжные варианты исправления
Экспортируйте 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:
cpptypedef 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.
Оставить C++ сигнатуру, но:
.def
файл с алиасом неманглированного имени;GetProcAddress
по могласному имени (узнать через dumpbin /exports TEST_FUNC.dll
);/MD
(общий CRT).std::vector
через DLL — источник тонких падений.Мелочи, на которые стоит взглянуть
__cdecl
и в DLL, и в typedef
.GetProcAddress
.FreeLibrary
до тех пор, пока не закончите работу со всеми буферами, которые освобождаются функциями из DLL (в варианте A — вызвать *_Free
до FreeLibrary
).Итог
nullptr
(из-за C++-мэнглинга).float**
/len
и отдельной функцией освобождения — это снимет класс проблем со std::vector
через границу DLL.