【发布时间】:2020-08-08 08:11:59
【问题描述】:
我有一个问题,可能是 C++ 线程中的内存泄漏。我收到代码 11 的运行时错误。我正在编写一个优化算法,旨在优化 2D 反应器的参数。它生成重整函数的实例,该函数创建重整器对象。重整器有 2 个不同的参数,它们在单个重整器中可以局部不同,并从主函数传递给重整函数。为了指定,每个重整器被划分为指定数量的区域(每个重整器中的尺寸和位置相同),并且每个区域可以具有不同的参数。因此,2 个向量中的每一个的大小等于 [NUMBER OF REFORMERS] * [NUMBER OF ZONES]。然后,重组函数创建Segment对象,其数量等于区域的数量。
我认为这里的问题是线程试图同时访问同一个向量,我真的很感激这个问题的解决方案。
备注:
- 如果我更改 main.cpp 以用通常的循环替换线程,则不会返回错误。
- 如果我在 set_segments 函数中注释掉 setProp 方法,则不会返回错误(带有线程)。
这里强烈推荐线程,因为单个Reformer的计算时间长,并且我可以访问多核计算单元。
为了澄清,我将用一个可重现的最小示例来解释所有内容:
输入.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;
改革者.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++;
}
}
}
【问题讨论】:
-
内存泄漏不应产生运行时错误。你的
main函数在哪里? -
@DmitryKuzminov,我不是 C++ 向导,所以我不知道“运行时错误”是否有一些我不知道的特殊、狭窄的含义,但程序无法继续永远泄漏内存。 一些坏事最终一定会发生。
-
@Padzak,如果他们知道“代码 11”是什么意思,这里可能有人可以提供帮助。您能否将错误消息的全文添加到问题中,或许还可以告诉我们运行该程序的操作系统是什么以及您使用什么工具来构建它?
-
什么是
spec_max,为什么只保留reactor_no == 2线程? -
对于不一致之处,我深表歉意,我是自学成才,有时仍然有些挣扎。我正在使用 CLion,IDE 返回了代码 11。两个线程只是一个例子,在原始代码中我生成了30个线程。
标签: c++ multithreading memory-leaks parallel-processing stdvector