diff --git a/src/Highs.h b/src/Highs.h index 4122482286..908471fd19 100644 --- a/src/Highs.h +++ b/src/Highs.h @@ -22,6 +22,7 @@ #include "lp_data/HighsRanging.h" #include "lp_data/HighsSolutionDebug.h" #include "model/HighsModel.h" +#include "util/HighsExceptions.h" #include "presolve/ICrash.h" #include "presolve/PresolveComponent.h" diff --git a/src/presolve/HPresolve.cpp b/src/presolve/HPresolve.cpp index 9d9dfbbe18..e5a078401a 100644 --- a/src/presolve/HPresolve.cpp +++ b/src/presolve/HPresolve.cpp @@ -18,6 +18,7 @@ #include #include "Highs.h" +#include "HighsExceptions.h" #include "io/HighsIO.h" #include "lp_data/HConst.h" #include "lp_data/HStruct.h" @@ -3993,7 +3994,12 @@ HPresolve::Result HPresolve::presolve(HighsPostsolveStack& postsolve_stack) { } }; - HPRESOLVE_CHECKED_CALL(initialRowAndColPresolve(postsolve_stack)); + try { + HPRESOLVE_CHECKED_CALL(initialRowAndColPresolve(postsolve_stack)); + } catch (const DataStackOverflow& e) { + // Here we re-throw the error + throw PresolveTooLarge(e.what()); + } HighsInt numParallelRowColCalls = 0; #if ENABLE_SPARSIFY_FOR_LP diff --git a/src/presolve/HPresolve.h b/src/presolve/HPresolve.h index 7017c1fa21..936d74a2ef 100644 --- a/src/presolve/HPresolve.h +++ b/src/presolve/HPresolve.h @@ -33,6 +33,7 @@ #include "util/HighsHash.h" #include "util/HighsLinearSumBounds.h" #include "util/HighsMatrixSlice.h" +#include "util/HighsExceptions.h" namespace presolve { diff --git a/src/presolve/HighsPostsolveStack.h b/src/presolve/HighsPostsolveStack.h index 3633056f88..abd5c84608 100644 --- a/src/presolve/HighsPostsolveStack.h +++ b/src/presolve/HighsPostsolveStack.h @@ -24,6 +24,7 @@ #include #include +#include "HighsExceptions.h" #include "lp_data/HConst.h" #include "lp_data/HStruct.h" #include "lp_data/HighsOptions.h" @@ -367,17 +368,23 @@ class HighsPostsolveStack { template void fixedColAtLower(HighsInt col, double fixValue, double colCost, const HighsMatrixSlice& colVec) { - assert(std::isfinite(fixValue)); - colValues.clear(); - for (const HighsSliceNonzero& colVal : colVec) - colValues.emplace_back(origRowIndex[colVal.index()], colVal.value()); - - reductionValues.push(FixedCol{fixValue, colCost, origColIndex[col], - HighsBasisStatus::kLower}); - reductionValues.push(colValues); - reductionAdded(ReductionType::kFixedCol); + try { + assert(std::isfinite(fixValue)); + colValues.clear(); + for (const HighsSliceNonzero& colVal : colVec) + colValues.emplace_back(origRowIndex[colVal.index()], colVal.value()); + + reductionValues.push(FixedCol{fixValue, colCost, origColIndex[col], + HighsBasisStatus::kLower}); + reductionValues.push(colValues); + reductionAdded(ReductionType::kFixedCol); + } catch (const DataStackOverflow& e) { + std::cerr << "Memory allocation failed while processing fixedColAtLower: " + << std::endl; + // Rethrow. + throw; + } } - template void fixedColAtUpper(HighsInt col, double fixValue, double colCost, const HighsMatrixSlice& colVec) { diff --git a/src/util/HighsDataStack.h b/src/util/HighsDataStack.h index 4a4be05601..d9f15afc45 100644 --- a/src/util/HighsDataStack.h +++ b/src/util/HighsDataStack.h @@ -18,9 +18,11 @@ #define UTIL_HIGHS_DATA_STACK_H_ #include +#include #include #include +#include "util/HighsExceptions.h" #include "util/HighsInt.h" #if __GNUG__ && __GNUC__ < 5 @@ -39,11 +41,19 @@ class HighsDataStack { template ::type = 0> void push(const T& r) { - std::size_t dataSize = data.size(); - data.resize(dataSize + sizeof(T)); + HighsInt dataSize = data.size(); + HighsInt newSize = dataSize + sizeof(T); + try { + data.resize(newSize); + } catch (const std::length_error& e) { + throw DataStackOverflow( + "Failed to resize the vector. Requested new size: " + + std::to_string(newSize) + ". Size to add is " + + std::to_string(sizeof(T)) + "for "+ + ". Current size: " + std::to_string(data.size()) + "."); + } std::memcpy(data.data() + dataSize, &r, sizeof(T)); } - template ::type = 0> void pop(T& r) { diff --git a/src/util/HighsExceptions.h b/src/util/HighsExceptions.h new file mode 100644 index 0000000000..412e233f56 --- /dev/null +++ b/src/util/HighsExceptions.h @@ -0,0 +1,21 @@ +#pragma once +#include + +class DataStackOverflow : public std::runtime_error { +public: + explicit DataStackOverflow(const std::string& msg) + : std::runtime_error(msg) {} +}; + +class ProblemTooLargeException : public std::runtime_error { +public: + explicit ProblemTooLargeException(const std::string& msg) + : std::runtime_error(msg) {} +}; + + +class PresolveTooLarge : public std::runtime_error { +public: + explicit PresolveTooLarge(const std::string& msg) + : std::runtime_error(msg) {} +};