У меня проблема, вероятно, с утечкой памяти в потоках C ++. Я получаю ошибку времени выполнения с кодом 11. Я пишу алгоритм оптимизации, который направлен на оптимизацию параметров 2D реакторов. Он генерирует экземпляры функции реформирования, которая создает объекты реформатора. Реформаторы имеют 2 разных параметра, которые могут локально отличаться в одном реформинге и передаются в функцию реформинга из основной функции. Чтобы указать, каждый реформатор разделен на определенное количество зон (одинаковые размеры и местоположения в каждом реформаторе), и каждая зона может иметь разные параметры. Следовательно, размер каждого из 2 векторов равен [КОЛИЧЕСТВО РЕФОРМАТОРОВ] * [КОЛИЧЕСТВО ЗОН]. Затем функция реформирования создает объекты сегмента, число которых равно количеству зон.
Я предполагаю, что проблема заключается в том, что потоки пытаются получить доступ к одному и тому же вектору одновременно, и я был бы очень признателен за решение этой проблемы. Вопрос.
Примечания:
- Если я изменю основной. cpp, чтобы заменить потоки обычным l oop, ошибки не будет возвращено.
- Если я закомментирую метод setProp в функциях set_segments, ошибка не будет возвращена (с потоками).
Здесь настоятельно рекомендуются потоки из-за большого времени вычислений одного реформатора, и у меня есть доступ к многоядерным вычислительным блокам.
Для пояснения я объясню все с минимальным воспроизводимым примером:
input.h
#include <iostream>
#include <fstream>
#include <vector>
#include <thread>
int reactor_no = 2; // number of reformers
int zones_X = 5; // number of zones in a single reformer, X direction
int zones_Y = 2; // number of zones in a single reformer, Y direction
double dim_X = 0.5; // reactor's length
double dim_Y = 0.2; // reactor's height
double wall_t = 0.1; // thickness of the reactor wall
size_t zones = zones_X * zones_Y;
Reformer.h:
#include "input.h"
class Reformer {
public:
Reformer() {}
Reformer(const double& L, const double& Y, const double& wall_t,
const int& zones_X = 1, const int& zones_Y = 1) {
length_ = L;
height_ = Y;
zonesX_ = zones_X;
zonesY_ = zones_Y;
wall_thickness_ = wall_t;
dx_ = length_ / static_cast<double> (zonesX_);
dr_ = height_ / static_cast<double> (zonesY_);
}
private:
double wall_thickness_; // wall thickness (m)
double length_; // recactor length (m)
double height_; // reactor height (m) (excluding wall thickness)
int zonesX_; // number of segments in the X direction
int zonesY_; // number of segments in the Y direction
double dx_; // segment width (m)
double dr_; // segment height (m)
}
Segment.h:
#include "input.h"
class Segment{
public:
Segment() : Segment(0, 0) {}
Segment(int i, int j) {
i_ = i;
j_ = j;
}
void setXR(const double& dx, const double& dr, const int& SL, const int& SR) {
x0_ = i_ * dx;
x1_ = x0_ + dx;
r0_ = j_ * dr;
r1_ = r0_ + dr;
if (i_ == SL - 1) {
x1_ = length;
}
if (j_ == SR - 1) {
r1_ = radius;
}
}
void setWall() {
x0_ = 0;
x1_ = length;
r0_ = radius;
r1_ = radius + wall_t;
}
void setProp(const double& por, const double& por_s, const bool& cat) {
porosity_ = por;
catalyst_ = cat;
}
private:
size_t i_; //segment column no.
size_t j_; //segment row no.
double x0_; //beginning of segment - x coordinate (m)
double x1_; //ending of segment - x coordinate (m)
double r0_; //beginning of segment - r coordinate (m)
double r1_; //ending of segment - r coordinate (m)
int catalyst_; //1 - catalytic, 0 - non-catalytic
double porosity_; //porosity (-)
};
main. cpp:
#include "input.h"
int main() {
int zones = zones_X * zones_Y;
size_t pop_size = reactor_no * zones;
std::vector<int> cat;
cat.reserve(pop_size);
std::vector<double> porosity;
porosity.reserve(pop_size); // the values in the vectors are not important, therefore I will just fill them with 1s
for (int i = 0; i < pop_size; i++) {
cat[i] = 1;
porosity[i] = 1.0;
}
std::vector<std::thread> Ref;
Ref.reserve(reactor_no);
for (k = 0; k < reactor_no; k++) {
Ref.emplace_back(reforming, k, cat, porosity);
}
for (auto &X : Ref) { X.join(); }
}
reforming. cpp:
#include "input.h"
void reforming(const int m, const std::vector<int>& cat_check, const std::vector<double>& por) {
Reformer reactor(length, radius, wall_t, zonesX, zonesY);
std::vector<Segment> seg; // vector holding segment objects
seg.reserve(zones);
set_segments(seg, reactor, zones, m, por, por_s, cat_check);
}
set_segments функция:
#include "input.h"
void set_segments(std::vector<Segment> &seg, Reformer &reac, const int m,
const std::vector<double> &por, const std::vector<int> &check) {
int i, j, k, n;
double dx = dim_X / static_cast<double> (zones_X);
double dy = dim_Y / static_cast<double> (zones_Y);
std::vector<Segment*> ptr_seg;
ptr_seg.reserve(zones);
k = 0;
for (i = 0; i < zones_X; i++) {
for (j = 0; j < zones_Y; j++) {
n = m * zones + (i * zones_Y + j);
seg.emplace_back(Segment(i, j));
seg[k].setProp(por[n], check[n]);
seg[k].setXR(dx, dy, zones_X, zones_Y);
k++;
}
}
}