R.pop_back(); - в этой строчке у меня вызываетс...
創建於:2025年9月6日
創建於:2025年9月6日
textR.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
{
textif (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;
}
}
}
textif (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);
}
}
textR.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); } }
Коротко: R.pop_back()
падает не потому, что «вектор обязательно пустеет логически», а потому что в какой-то итерации к моменту вызова pop_back()
у R
действительно size()==0 (или разрушается «битый» элемент). Ниже — самые частые причины именно при таком паттерне pop_heap
→ move R.back()
→ pop_back()
и что проверить.
pop_heap
/pop_back
std::pop_heap(R.begin(), R.end(), Compare);
добавьте защиту:
Если сработает — значит где-то ранее вы вышли из цикла без «восполнения» кучи.cppif (R.empty()) { /* лог/ассерт */ return Extr; }
Это нормально (вы просто выходите), но на следующей итерации цикла вы уже не будете (вы вышли). Так что эта часть не делаетcppstd::pop_heap(...); Interval i = std::move(R.back()); R.pop_back(); // уменьшили size ... if (++schetchick == global_iterations || dmin < epsilon) { return Extr; // выход без возвращения интервала назад }
R
пустым «для следующего pop_back».pop_back
в той же итерации — значит проблема не в этом «раннем выходе».Compare
Compare
обязан задавать строгий слабый порядок (Strict Weak Ordering). Любые нарушения (недетерминизм, зависимость от меняющихся полей без переупорядочивания, NaN в сравниваемых значениях и т. п.) приводят к UB и повреждению внутреннего состояния вектора/кучи, что легко «выстрелит» на pop_back
.R[i].M
и длины интервалов. Где вы меняли ключи кучи, вы вызвали std::make_heap(R.begin(), R.end(), Compare);
— это хорошо. Убедитесь, что во всех ветках, где меняются поля, влияющие на порядок (то, по чему сравнивает Compare
), вы действительно делаете reheapify.Это ок, еслиcppelse { curr.ChangeCharacteristic(m, N); curr1.ChangeCharacteristic(m, N); // R[i] не меняли → make_heap не нужен }
Compare
не зависит от других полей в R[i]
. Но если ChangeCharacteristic
косвенно влияет на то, как Compare
сравнит элементы (например, через общий глобальный коэффициент), потребуется make_heap
.Interval
вызывает деструктор элемента на конце. Если уcppInterval promejutochny_otrezok = std::move(R.back()); R.pop_back();
Interval
деструктор бросает (нельзя), assert’ится, или опирается на инварианты, нарушающиеся после перемещения — исключение прилетит на pop_back()
.
Проверьте:
~Interval()
— noexcept
и безопасен для «перемещённого» состояния.delete
/free
).Compare
использует float
поля (M
, длина интервала) и туда закрадывается NaN
, любые сравнения становятся непредсказуемыми → куча ломается.dmax
, GLOBAL_FACTOR
, MULTIPLIER = (1.0f / dmax) * Mmax
(если dmax==0
, деление!), fmaf
, т. п.
Добавьте ранние проверки:
cppassert(std::isfinite(dmax) && dmax > 0); assert(std::isfinite(Mmax)); assert(std::isfinite(curr.M) && std::isfinite(curr1.M));
R.emplace_back(...)
вы не делаете make_heap
. Для size()==1
это ок (куча тривиальна). Но как только размер >1, вы строго поддерживаете кучу через push_heap
— это правильно. Убедитесь, что нигде не попадает во R
элемент обходя push_heap
.pop_heap
/move
/pop_back
pop_heap
→ максимальный элемент уходит в back()
;move
из back()
;pop_back
разрушает перемещённый элемент._ITERATOR_DEBUG_LEVEL=2
, ассерты на пустоту и std::isfinite
.cppassert(!R.empty()); std::pop_heap(...); // здесь size тот же // R.back() валиден Interval x = std::move(R.back()); R.pop_back(); // size--, деструктор
Interval
на POD/тривиальный тип или сделайте пустой деструктор — если падение исчезло, проблема в деструкторе/перемещении.Если выяснится, что иногда вы меняете ключи элементов без reheapify, то самый простой «страховочный» шаг — всегда пересобирать кучу после любых модификаций полей, влияющих на порядок:
cpp// После любых ChangeCharacteristic, которые влияют на Compare: std::make_heap(R.begin(), R.end(), Compare);
И убедитесь, что деления на dmax
безопасны (dmax>0
) и что Compare
— чистая функция по полям элемента.
Если пришлёте код Interval
и Compare
, скажу точнее, что именно ломает кучу/деструктор.