R.pop_back(); - в этой строчке у меня вызываетс...

Creado el: 6 de septiembre de 2025

Respondido usando GPT-5 por Chat01

Pregunta

text
R.pop_back(); - в этой строчке у меня вызывается исключение, но я не понимаю с чем это может быть связано так как на каждой итерации алгоритма у меня удаляется один интервал и вместо него добавляются два новых это просто невозможно чтобы вектор опустел: static __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 float seed) noexcept

{

text
if (N == 1u) { const float initial_length = b - a; float dmax = initial_length; const float start_val = ShekelFunc(a, seed); float best_f = 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(start_val, best_f); std::vector<float> Extr; Extr.reserve((global_iterations << 1u) + 4u); std::vector<Interval> R; R.reserve(global_iterations + 1u); R.emplace_back(std::make_pair(a, start_val), std::make_pair(b, best_f), N); float Mmax = R.back().M; float m = r * Mmax; const float threshold_03 = 0.3f * initial_length; const float inv_threshold_03 = 1.0f / threshold_03; while (true) { const float new_point = Shag(m, x_Rmax.first, x_Rmax.second, y_Rmax.first, y_Rmax.second, N, r); const float new_value = ShekelFunc(new_point, seed); const std::pair<float, float> promejutochnaya_tochka{ new_point, new_value }; if (new_value < best_f) { best_f = new_value; Extr.emplace_back(best_f); Extr.emplace_back(new_point); } std::pop_heap(R.begin(), R.end(), Compare); Interval promejutochny_otrezok = std::move(R.back()); R.pop_back(); const size_t r_size = R.size(); const float len2 = promejutochny_otrezok.end.first - new_point; const float len1 = new_point - promejutochny_otrezok.start.first; const float dmin = len1 < len2 ? len1 : len2; if (++schetchick == global_iterations || dmin < epsilon) { Extr.emplace_back(dmin); Extr.emplace_back(schetchick); return Extr; } Interval curr(promejutochny_otrezok.start, promejutochnaya_tochka, N); Interval curr1(promejutochnaya_tochka, promejutochny_otrezok.end, N); const float currM = curr.M > curr1.M ? curr.M : curr1.M; if (len2 + len1 == dmax) { dmax = len2 > len1 ? len2 : len1;

#pragma loop(ivdep)
for (size_t i = 0u; i < r_size; ++i) {
const float len = R[i].end.first - R[i].start.first;
if (len > dmax) {
dmax = len;
}
}
}

text
if (mode) { if (threshold_03 > dmax && schetchick % 3u == 0u || 10.0f * dmax < initial_length) { if (currM > Mmax) { Mmax = currM; m = r * Mmax; } const float progress = fmaf(-inv_threshold_03, dmax, 1.0f); const float alpha = fmaf(progress, progress, 1.0f); const float betta = 2.0f - alpha; const float MULTIPLIER = (1.0f / dmax) * Mmax; const float global_coeff = fmaf(MULTIPLIER, r, -MULTIPLIER); const float GLOBAL_FACTOR = betta * global_coeff; curr.ChangeCharacteristic(fmaf(GLOBAL_FACTOR, len1, curr.M * alpha), N); curr1.ChangeCharacteristic(fmaf(GLOBAL_FACTOR, len2, curr1.M * alpha), N);

#pragma loop(ivdep)
for (size_t i = 0u; i < r_size; ++i) {
const float len_item = R[i].end.first - R[i].start.first;
R[i].ChangeCharacteristic(fmaf(GLOBAL_FACTOR, len_item, R[i].M * alpha), N);
}
std::make_heap(R.begin(), R.end(), Compare);
}
else {
if (currM > Mmax) {
Mmax = currM;
m = r * Mmax;
curr.ChangeCharacteristic(m, N);
curr1.ChangeCharacteristic(m, N);
#pragma loop(ivdep)
for (size_t i = 0u; i < r_size; ++i) {
R[i].ChangeCharacteristic(m, N);
}
std::make_heap(R.begin(), R.end(), Compare);
}
else {
curr.ChangeCharacteristic(m, N);
curr1.ChangeCharacteristic(m, N);
}
}
}
else {
if (currM > Mmax) {
Mmax = currM;
m = r * Mmax;
curr.ChangeCharacteristic(m, N);
curr1.ChangeCharacteristic(m, N);
#pragma loop(ivdep)
for (size_t i = 0u; i < r_size; ++i) {
R[i].ChangeCharacteristic(m, N);
}
std::make_heap(R.begin(), R.end(), Compare);
}
else {
curr.ChangeCharacteristic(m, N);
curr1.ChangeCharacteristic(m, N);
}
}

text
R.emplace_back(std::move(curr)); std::push_heap(R.begin(), R.end(), Compare); R.emplace_back(std::move(curr1)); std::push_heap(R.begin(), R.end(), Compare); const Interval& top = R.front(); x_Rmax = std::make_pair(top.start.first, top.end.first); y_Rmax = std::make_pair(top.start.second, top.end.second); } }

Pensamiento

Considering size behavior

When size can be 0, it's after popping one and possibly an early return. The return happens before new intervals are added, so it's fine. Later, size becomes r_size + 2. Initially, r_size is 0, leading to a final size of 2. However, when adjustments call std::make_heap, it then pushes two items. Could there be issues with the comparator using a moved-from object? Before popping, the object state might be invalid, but then it's destroyed.

Considering exception cause

The exception may be related to how the custom comparator is used with std::push_heap/pop_heap, which requires consistency for max-heaps. After modifying R[i].ChangeCharacteristic, they rebuild the heap with std::make_heap. However, if ChangeCharacteristic throws, it could cause issues—though that's unlikely. The exception happens during R.pop_back() when R.size() == 0, which aligns with MSVC debug behavior.

Identifying heap issue

It seems the issue stems from accessing R.back() when the vector is empty, which would normally assert. But since pop_heap requires a non-empty heap, this causes undefined behavior. The solution? You need to call std::make_heap(R.begin(), R.end(), Compare) after the first emplace_back to ensure the vector is a valid heap before using pop_heap.

Fixing heap and comparator logic

To fix the issue, after R.emplace_back(...), you need to call std::make_heap(R.begin(), R.end(), Compare);. Also, ensure Compare provides strict weak ordering that remains consistent with ChangeCharacteristic. Pay attention to whether Compare defines a max-heap or min-heap. Always assert that R is not empty before calling pop_heap and be cautious of potential NaNs, which could break the comparator logic.

Thought for 20s

Respuesta

Почти наверняка проблема в том, что вы вызываете std::pop_heap на диапазоне, который ещё ни разу не был преобразован в кучу. Сразу после первого emplace_back вектор R НЕ является кучей, а алгоритмы pop_heap/push_heap требуют, чтобы диапазон уже удовлетворял свойствам кучи. В результате первый же pop_heap(R.begin(), R.end(), Compare) — это UB; в MSVC-дебаге это часто проявляется как “исключение” на R.pop_back() (на деле контейнер уже в некорректном состоянии).

Что исправить

Сразу после первичной вставки элемента в R сделайте make_heap:

cpp
R.emplace_back(std::make_pair(a, start_val), std::make_pair(b, best_f), N); std::make_heap(R.begin(), R.end(), Compare); // <— ВАЖНО: инициализация кучи float Mmax = R.back().M; float m = r * Mmax;

Дальше вы уже корректно используете push_heap после каждого emplace_back и периодически пересобираете кучу make_heap после массовых изменений при ChangeCharacteristic.

Дополнительные «минные поля»

  1. Проверка пустоты перед pop (на случай будущих правок):
cpp
if (R.empty()) { /* обработать ситуацию или assert */ } std::pop_heap(R.begin(), R.end(), Compare); Interval promejutochny_otrezok = std::move(R.back()); R.pop_back();
  1. Корректность компаратора. Убедитесь, что Compare задаёт строгий слабый порядок и не опирается на меняющееся внешнее состояние. Иначе pop_heap/make_heap могут вести себя непредсказуемо.

  2. NaN/Inf в ключах кучи. У вас есть участок:

cpp
const float MULTIPLIER = (1.0f / dmax) * Mmax;

Если dmax когда-нибудь станет нулём, получите Inf/NaN, и сравнения в Compare перестанут быть строгими → кучу «ломает». Подстелите соломку:

cpp
if (dmax <= std::numeric_limits<float>::epsilon()) { // зафиксировать коэффициенты, пересчитать dmax или выйти }
  1. Равенства на float. Сравнение if (len2 + len1 == dmax) лучше заменить на сравнение с допуском.

После добавления одного std::make_heap сразу после первой вставки проблема с R.pop_back() должна исчезнуть.

Compartir este Q&A