std::fill数组较大时出现segmentation fault错误
std::fill segmentation fault error when the array is large
我有下面的class,它类似于二维的标量场,但由于可能使用周期性边界条件,因此也有幻影区(只需将其视为二维矩阵)。
#include <algorithm>
#include <iostream>
#include <fftw3.h>
class RectMesh
{
private:
int cols_x;
int rows_y;
int nghost;
double* mesh;
public:
void CheckConstr(int& cols, int& rows, int& ghost);
RectMesh(int cols=2, int rows=2, int ghost=1);
/* Rule of 5 */
~RectMesh();
RectMesh(const RectMesh& obj);
RectMesh(RectMesh&& tmp) noexcept;
RectMesh& operator=(RectMesh rhs);
RectMesh& operator=(RectMesh&& tmp);
};
构造函数实现是
/*--------------------- Constructor -----------------------------*/
void RectMesh::CheckConstr(int& cols, int& rows, int& ghost)
{
if (cols < 2 || rows < 2 || ghost < 0)
{
std::cout << "The smallest mesh must have dimensions (2x2)"
"and the minimum number of ghost points is zero. Exiting."
<< std::endl;
exit(EXIT_FAILURE);
}
}
RectMesh::RectMesh(int cols, int rows, int ghost)
: cols_x(cols), rows_y(rows), nghost(ghost), mesh(nullptr)
{
CheckConstr(cols,rows,ghost);
int len = (cols_x+2*nghost)*(rows_y + 2*nghost);
mesh = (double*) fftw_malloc(len*sizeof(double));
std::fill(mesh, mesh+len, 0.0);
std::cout << "RectMesh constructor called." << std::endl;
}
主要功能
int main()
{
int cols = 1e6;
int rows = 1e6;
int nghost = 2;
RectMesh A(cols,rows,nghost);
return 0;
}
控制台输出:
Segmentation fault (core dumped)
当我注释掉 std::fill
或当我有 rows = cols = 1e5
.
时,这不会发生
这是为什么?
假设您是 运行 一台普通或典型的计算机,1e6 列乘 1e6 行的 double
s 是
1000000 * 1000000 * 8 bytes = 8 TB (or 7.28 TiB)
所以答案是:检查 fftw_malloc
的 return 值,而您没有检查。有可能 它失败了并且 return 编辑了一个空指针 ,这肯定会在您尝试访问它时造成混乱。
另外,检查乘法的结果。 int
很可能是 4 字节并且不包含这样的值(一些 43 位整数)。改用 size_t
。
如果将每个维度减小到 1e5,结果将是 80 GB (74.51 GiB),这可能适合大型服务器。
int len = (cols_x+2*nghost)*(rows_y + 2*nghost);
cols_x
和rows_y
代入1e6,nghost
代入2,然后乘以sizeof(double)
即8,总计为:
8000064000128
字节,或您尝试分配的超过 7 TB 的内存。这里发生了两件事之一:
fftw_malloc
对此大笑,returns NULL
,您显示的代码无法检查其 return 值,并发现没有分配任何东西,或者
实际乘法溢出(如果在 32 位平台上),结果同样荒谬。
我有下面的class,它类似于二维的标量场,但由于可能使用周期性边界条件,因此也有幻影区(只需将其视为二维矩阵)。
#include <algorithm>
#include <iostream>
#include <fftw3.h>
class RectMesh
{
private:
int cols_x;
int rows_y;
int nghost;
double* mesh;
public:
void CheckConstr(int& cols, int& rows, int& ghost);
RectMesh(int cols=2, int rows=2, int ghost=1);
/* Rule of 5 */
~RectMesh();
RectMesh(const RectMesh& obj);
RectMesh(RectMesh&& tmp) noexcept;
RectMesh& operator=(RectMesh rhs);
RectMesh& operator=(RectMesh&& tmp);
};
构造函数实现是
/*--------------------- Constructor -----------------------------*/
void RectMesh::CheckConstr(int& cols, int& rows, int& ghost)
{
if (cols < 2 || rows < 2 || ghost < 0)
{
std::cout << "The smallest mesh must have dimensions (2x2)"
"and the minimum number of ghost points is zero. Exiting."
<< std::endl;
exit(EXIT_FAILURE);
}
}
RectMesh::RectMesh(int cols, int rows, int ghost)
: cols_x(cols), rows_y(rows), nghost(ghost), mesh(nullptr)
{
CheckConstr(cols,rows,ghost);
int len = (cols_x+2*nghost)*(rows_y + 2*nghost);
mesh = (double*) fftw_malloc(len*sizeof(double));
std::fill(mesh, mesh+len, 0.0);
std::cout << "RectMesh constructor called." << std::endl;
}
主要功能
int main()
{
int cols = 1e6;
int rows = 1e6;
int nghost = 2;
RectMesh A(cols,rows,nghost);
return 0;
}
控制台输出:
Segmentation fault (core dumped)
当我注释掉 std::fill
或当我有 rows = cols = 1e5
.
这是为什么?
假设您是 运行 一台普通或典型的计算机,1e6 列乘 1e6 行的 double
s 是
1000000 * 1000000 * 8 bytes = 8 TB (or 7.28 TiB)
所以答案是:检查 fftw_malloc
的 return 值,而您没有检查。有可能 它失败了并且 return 编辑了一个空指针 ,这肯定会在您尝试访问它时造成混乱。
另外,检查乘法的结果。 int
很可能是 4 字节并且不包含这样的值(一些 43 位整数)。改用 size_t
。
如果将每个维度减小到 1e5,结果将是 80 GB (74.51 GiB),这可能适合大型服务器。
int len = (cols_x+2*nghost)*(rows_y + 2*nghost);
cols_x
和rows_y
代入1e6,nghost
代入2,然后乘以sizeof(double)
即8,总计为:
8000064000128
字节,或您尝试分配的超过 7 TB 的内存。这里发生了两件事之一:
fftw_malloc
对此大笑,returnsNULL
,您显示的代码无法检查其 return 值,并发现没有分配任何东西,或者实际乘法溢出(如果在 32 位平台上),结果同样荒谬。