видишь ли в чём проблема - в консольном приложении...
बनाया गया: 2 सितंबर 2025
का उपयोग करके उत्तर दिया गया GPT-5 Thinking द्वारा Chat01
बनाया गया: 2 सितंबर 2025
का उपयोग करके उत्तर दिया गया GPT-5 Thinking द्वारा Chat01
видишь ли в чём проблема - в консольном приложении это работает (функция xor_rand и функция шекеля static inline float ShekelFunc(float x, uint32_t seed)
{
uint32_t i = 0u;
float res = 0.0f;
uint32_t current_state = seed; // Локальная копия для изменений
textwhile (i < 10u) { const float x_part = fmaf(-xor_rand(current_state), 10.0f, x); res -= 1.0f / fmaf(fmaf(xor_rand(current_state), 20.0f, 5.0f), x_part * x_part, fmaf(xor_rand(current_state), 0.2f, 1.0f)); ++i; } return res;
} ... static float xor_rand(uint32_t& state) // Принимает state по ссылке для изменения
{
state ^= state << 13u;
state ^= state >> 17u;
state ^= state << 5u;
return state * 0x1.0p-32f;
}) без исключений но когда я использую эти функции в экспортируемой функции в моей DLL которая вызывается в управляемом коде winforms c++/clr по нажатию кнопки то я получаю SEH исключения static 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)
{
std::ofstream logfile("function_debug.log", std::ios_base::app);
logfile << "=== Base_LNA_1_2_Mer_AGP called ===" << std::endl;
textif (N == 1u) { logfile << "N == 1u branch" << std::endl; try { const float initial_length = b - a; float dmax = initial_length; std::vector<float> Extr; Extr.reserve((global_iterations << 1u) + 2u); std::vector<Interval> R; R.reserve(global_iterations + 1u); logfile << "Before ShekelFunc(a, seed)" << std::endl; float best_f = ShekelFunc(b, seed); logfile << "ShekelFunc(a, seed) = " << best_f << std::endl; logfile << "Before ShekelFunc(b, seed)" << std::endl; const float end_val = ShekelFunc(b, seed); logfile << "ShekelFunc(b, seed) = " << end_val << std::endl; uint32_t schetchick = 0u; std::pair<float, float> x_Rmax = std::make_pair(a, b); std::pair<float, float> y_Rmax = std::make_pair(best_f, end_val); logfile << "Before Interval creation" << std::endl; Interval interval(std::pair(a, best_f), std::pair(b, end_val), N); logfile << "Interval created successfully" << std::endl; logfile << "Before push to priority_queue" << std::endl; R.push_back(interval); logfile << "Push to priority_queue completed" << std::endl; //const float initial_length = b - a; //float dmax = initial_length; //std::vector<float> Extr; //Extr.reserve((global_iterations << 1u) + 2u); //std::vector<std::unique_ptr<Interval>> R; //R.reserve(global_iterations + 1u); //Priority_queue R; //float best_f = ShekelFunc(a, seed); //const float end_val = ShekelFunc(b, seed); //uint32_t schetchick = 0u; //std::pair<float, float> x_Rmax = std::make_pair(a, b); //std::pair<float, float> y_Rmax = std::make_pair(best_f, end_val); //R.emplace_back(std::make_unique<Interval>(std::make_pair(a, best_f), std::make_pair(b, end_val), 1u)); //float Mmax = R.front().M; //float m = r * Mmax; std::vector<float> myVector = { 1.1f, 2.2f, 3.3f, 4.4f, 5.5f }; for (float& num : myVector) { num *= 1.1f; } myVector.push_back(6.6f); logfile << "Returning result" << std::endl; return myVector; } catch (const std::exception& e) { logfile << "std::exception in Base_LNA_1_2_Mer_AGP: " << e.what() << std::endl; // Дополнительная информация об исключении std::stringstream ss; ss << "Exception details: N=" << N << ", a=" << a << ", b=" << b << ", seed=" << seed << ", what(): " << e.what(); logfile << ss.str() << std::endl; throw; } catch (const std::string& e) { logfile << "String exception in Base_LNA_1_2_Mer_AGP: " << e << std::endl; throw; } catch (int e) { logfile << "Integer exception in Base_LNA_1_2_Mer_AGP: " << e << std::endl; throw; } catch (...) { logfile << "Unknown exception in Base_LNA_1_2_Mer_AGP" << std::endl; // Попытка получить больше информации о неизвестном исключении try { std::rethrow_exception(std::current_exception()); } catch (const std::exception& e) { logfile << "Unwrapped exception: " << e.what() << std::endl; } catch (...) { logfile << "Completely unknown exception type" << std::endl; } throw; } } logfile << "N != 1u, returning empty vector" << std::endl; return std::vector<float>();
}
// 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)
{
std::ofstream logfile("dll_debug.log", std::ios_base::app);
logfile << "=== Function called ===" << std::endl;
logfile << "Parameters: N=" << N << ", a=" << a << ", b=" << b << ", c=" << c
<< ", d=" << d << ", r=" << r << ", mode=" << mode
<< ", epsilon=" << epsilon << ", seed=" << seed << std::endl;
text*out_data = nullptr; *out_len = 0; try { logfile << "Calling Base_LNA_1_2_Mer_AGP..." << std::endl; auto v = Base_LNA_1_2_Mer_AGP(N, global_iterations, a, b, c, d, r, mode, epsilon, seed); logfile << "Base_LNA_1_2_Mer_AGP completed, size: " << v.size() << std::endl; *out_len = static_cast<uint32_t>(v.size()); if (*out_len > 0) { *out_data = static_cast<float*>(CoTaskMemAlloc(sizeof(float) * (*out_len))); if (!*out_data) { logfile << "Memory allocation failed" << std::endl; return 2; } memcpy(*out_data, v.data(), sizeof(float) * (*out_len)); logfile << "Data copied successfully" << std::endl; } logfile << "Returning success" << std::endl; return 0; } catch (const std::exception& e) { logfile << "std::exception: " << e.what() << std::endl; // Получаем дополнительную информацию об исключении std::string ex_type = typeid(e).name(); logfile << "Exception type: " << ex_type << std::endl; return 1; } catch (const std::string& e) { logfile << "String exception: " << e << std::endl; return 1; } catch (int e) { logfile << "Integer exception: " << e << std::endl; return 1; } catch (...) { logfile << "Unknown exception occurred" << std::endl; // Попытка получить больше информации try { std::rethrow_exception(std::current_exception()); } catch (const std::exception& e) { logfile << "Unwrapped exception: " << e.what() << std::endl; } catch (...) { logfile << "Completely unknown exception type" << std::endl; } return 1; }
}
extern "C" __declspec(dllexport) void __cdecl Base_LNA_1_2_Mer_AGP_Free(float* p) {
CoTaskMemFree(p);
} это код в 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); uint32_t seed = GetTickCount(); typedef int(__cdecl* agp_c)( uint32_t, uint32_t, float, float, float, float, float, bool, float, uint32_t, float**, uint32_t*, char*, size_t); typedef void(__cdecl* agp_free)(float*); HINSTANCE h = LoadLibrary(L"TEST_FUNC.dll"); if (!h) { DWORD errorCode = GetLastError(); // Выводим код ошибки в текстовое поле textBox2->Text = "Ошибка загрузки DLL: " + errorCode.ToString(); return; } 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) { textBox2->Text = "Ошибка: не удалось получить функции из DLL"; FreeLibrary(h); return; } float* buf = nullptr; uint32_t len = 0; // Добавляем буфер для сообщения об ошибке const int ERROR_MSG_SIZE = 256; char error_msg[ERROR_MSG_SIZE] = { 0 }; try { int rc = f(1, 10000, 0.0f, 1.0f, -2.2f, 1.8f, 2.5f, false, 0.0001f, seed, &buf, &len, error_msg, ERROR_MSG_SIZE); if (rc == 0) { std::vector<float> Extr_2D(buf, buf + len); ffree(buf); textBox2->Text = "Результат: " + Convert::ToString(Extr_2D.back()); } else { // Попробуйте прочитать файл лога и показать его содержимое if (File::Exists("dll_debug.log")) { String^ logContent = File::ReadAllText("dll_debug.log"); textBox2->Text = "Код ошибки: " + rc.ToString() + "\n" + logContent; } else { textBox2->Text = "Код ошибки: " + rc.ToString() + " (лог не найден)"; } } } catch (const std::exception& ex) { textBox2->Text = "Исключение: " + gcnew String(ex.what()); } catch (...) { textBox2->Text = "Неизвестное исключение"; } FreeLibrary(h); - это код управляемый
Почти наверняка причина в несовпадении сигнатур при вызове экспортируемой функции.
В DLL у вас экспорт объявлен так:
cppextern "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);
А в C++/CLI вы объявляете указатель на функцию с двумя дополнительными параметрами (char*, size_t
) и именно так её вызываете:
cpptypedef int(__cdecl* agp_c)( uint32_t, uint32_t, float, float, float, float, float, bool, float, uint32_t, float**, uint32_t*, char*, size_t); // <- ЛИШНИЕ аргументы ... int rc = f(..., &buf, &len, error_msg, ERROR_MSG_SIZE); // <- передаёте лишние аргументы
На x86 такое несоответствие очень легко приводит к порче стека (если вдруг где-то окажется __stdcall, а не __cdecl — будет 100% краш), а на x64 тоже может кончиться SEH-исключением из-за неверной раскладки параметров/регистров. Именно поэтому в кнопке вы ловите SEHException
.
cpptypedef int(__cdecl* agp_c)( uint32_t, uint32_t, float, float, float, float, float, bool, float, uint32_t, float**, uint32_t*); int rc = f(1, 10000, 0.0f, 1.0f, -2.2f, 1.8f, 2.5f, false, 0.0001f, seed, &buf, &len);
__cdecl
.dumpbin /exports TEST_FUNC.dll
. Должно быть Base_LNA_1_2_Mer_AGP_C
(без декорации типа _@NN
, которая указывает на __stdcall).Для межмодульного ABI лучше избегать bool
(размер/ABI может расходиться между компиляторами/настройками). Надёжнее так:
bool mode
на uint32_t mode
(0/1) и аналогично в объявлении в приложении. (Это рекомендация на будущее; не обязательно для запуска, но повышает устойчивость ABI.)Если хотите действительно передавать буфер для текста ошибки из DLL — добавьте его и в экспорт и реализуйте заполнение в DLL, а не только в вызывающей стороне. Сейчас вызывающая сторона передаёт лишние аргументы, которые DLL не ожидает.
Пример корректного варианта экспорта с ошибочным сообщением (опционально):
cppextern "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, uint32_t mode, float epsilon, uint32_t seed, float** out_data, uint32_t* out_len, char* err, size_t err_cap) { __try { // ... ваш код ... return 0; } __except(EXCEPTION_EXECUTE_HANDLER) { // поймает SEH (AV и т.д.) if (err && err_cap) _snprintf_s(err, err_cap, _TRUNCATE, "SEH 0x%08X", GetExceptionCode()); return 1; } }
И соответствующий typedef
/вызов в кнопке с этими параметрами.
ShekelFunc(b, seed)
. Просто чтобы не путаться при диагностике — приведите в соответствие.__try
) можно собрать DLL с /EHa
, тогда catch(...)
поймает и SEH. Но лучше локально обернуть внешнюю С-обёртку в __try/__except
, как в примере выше.CoTaskMemAlloc/Free
— это безопасно для межмодульной передачи.С высокой вероятностью устранение несовпадения сигнатур (п.1–2) уберёт ваши SEH-исключения.