我有一个工作程序来分析C ++中的数据,这个数据产生了迄今为止35个成功的数据文件。我正在使用Code:Blocks中的Scientific Linux,当它正在工作时,除了涉及非常大的网格尺寸(1000x1000 +)的一些小错误,它完美地工作并且产生了我正在寻找的东西。
我最近切换到Ubuntu并期望它能正常工作但事实并非如此。它接受初始输入(第一个粒子开关)但随后立即崩溃并出现分段故障139.我试图在Windows中运行它而不是我的双启动但它似乎没有识别本地文件系统所以我被迫寻求帮助。
这是一个很长的程序,所以我会重现整个事情。我提前道歉。
// This program converts the column output of a 1D PIC code into a workable solution
#include <iostream>
#include <fstream>
#include <math.h>
using namespace std;
double calculateXMaximum(double arraymax[], int size)
{
double maximum = 0;
for (int k = 1; k < size/2; k++)
{
if(arraymax[2*k] > maximum)
{
maximum = arraymax[2*k];
}
}
return maximum;
}
double calculateXMinimum(double arraymin[], int size)
{
double minimum = 0;
for (int k = 1; k < size/2; k++)
{
if(arraymin[2*k] < minimum)
{
minimum = arraymin[2*k];
}
}
return minimum;
}
double calculatePXMaximum(double arraymax[], int size)
{
double maximum = 0;
for (int k = 1; k < size/2; k++)
{
if(arraymax[2*k+1] > maximum)
{
maximum = arraymax[2*k+1];
}
}
return maximum;
}
double calculatePXMinimum(double arraymin[], int size)
{
double minimum = 0;
for (int k = 1; k < size/2; k++)
{
if(arraymin[2*k+1] < minimum)
{
minimum = arraymin[2*k+1];
}
}
return minimum;
}
int main()
{
// Variables settable before running program - will set up initialisation later.
double xmin = 0;
double xmax = 0;
double pmin = 0;
double pmax = 0;
int xni = 0;
double xntemp = 0;
double deltax = 0;
int xi; // X interpolates, defined from console for resolution of diagram
int pnj = 0;
double pntemp = 0;
double deltap = 0;
int pi;
int type;
double modifier;
// Determines momentum modifier!
cout << "For particle type, enter 1 (e-) or 2 (p+)" << endl;
cout << "Particle type: ";
cin >> type;
if (type == 2)
{
modifier = 1836;
}
else
{
modifier = 1;
}
ifstream inputFile;
ofstream outputFile;
inputFile.open ("/home/Nick/fi020000.dat");
outputFile.open ("/home/Nick/fi20k.dat");
int dataformat[2];
for(int rd = 0; rd < 2; rd++)
{
dataformat[rd] = 0;
inputFile >> dataformat[rd];
}
int records = dataformat[1] + 2;
double data[records];
cout << "Number of particles: " << dataformat[1]/2 << endl;
// Introduction of data from input data file loop. Produces records.
for (int count = 0; count < records; count++)
{
inputFile >> data[count];
}
// Calling functions for xmin and xmax. May streamline later
xmax = calculateXMaximum(data, records) * 1.1;
cout << "Maximum x value: " << xmax << endl;
xmin = calculateXMinimum(data, records) * 1.1;
cout << "Minimum x value: " << xmin << endl;
pmax = calculatePXMaximum(data, records) * 1.1 / modifier;
cout << "Maximum p value: " << pmax << endl;
pmin = calculatePXMinimum(data, records) * 1.1 / modifier;
cout << "Minimum p value: " << pmin << endl;
// Definition of bin size
cout << "Entire desired number of x bins: ";
cin >> xi;
const int xip = xi;
cout << "Enter desired number of p bins: ";
cin >> pi;
const int pip = pi;
cout << "Grid is " << xip << " x " << pip << endl;
// Calculate DELTA X and DELTA P
deltax = (xmax - xmin)/(xip);
deltap = (pmax - pmin)/(pip);
cout << "Resolution of x: " << deltax << endl;
cout << "Resolution of p: " << deltap << endl;
int phaseSpace [xip][pip];
for(int i=0; i<xip; i++)
{
for(int j=0; j<pip; j++)
{
phaseSpace[i][j] = 0;
}
}
for (int phasecount=1; phasecount < (records/2)-1; phasecount++)
{
xntemp = (data[2*phasecount] - xmin)/deltax;
xni = floor(xntemp);
pntemp = ((data[(2*phasecount)+1] / modifier) - pmin)/deltap;
pnj = floor(pntemp);
phaseSpace[xni][pnj] = phaseSpace[xni][pnj] + 1;
}
for (int xoutcount = 0; xoutcount < xip; xoutcount++)
{
for (int poutcount = 0; poutcount < pip; poutcount++)
{
outputFile << xmin+((xoutcount+0.5)*deltax) << " " << pmin+((poutcount+0.5)*deltap) << " "<< phaseSpace[xoutcount][poutcount] << endl;
}
outputFile << endl;
}
cout << "Program complete" << endl;
return 0;
}
我的意图是在本周末完成一份30页的报告,现在我用来做这个的程序完全崩溃了。我不是计算机科学家 - 我是一名物理学家,不到一个月前我学习了C ++。因此,我不知道发生了什么。我知道这个话题已经被看了很多,但我真的不明白这个建议。
编辑:堆栈跟踪是:
#0 0x4010af ?? () (??:??)
#1 0x7ffff7215ea5 __libc_start_main() (/lib/x86_64-linux-gnu/libc.so.6:??)
#2 0x4017f1 ?? () (??:??)
EDIT2:Valgrind结果
==4089== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==4089== Command: ./Analysis
==4089==
For particle type, enter 1 (e-) or 2 (p+)
Particle type: 2
==4089== Warning: client switching stacks? SP change: 0x7fefff9c0 --> 0x7fe6d7118
==4089== to suppress, use: --max-stackframe=9603240 or greater
==4089== Invalid write of size 8
==4089== at 0x4010AF: ??? (in /home/paladin/Contour/Analysis/bin/Release/Analysis)
==4089== by 0x5673EA4: (below main) (libc-start.c:260)
==4089== Address 0x7fe6d7118 is on thread 1's stack
==4089==
==4089==
==4089== Process terminating with default action of signal 11 (SIGSEGV)
==4089== Access not within mapped region at address 0x7FE6D7118
==4089== at 0x4010AF: ??? (in /home/paladin/Contour/Analysis/bin/Release/Analysis)
==4089== If you believe this happened as a result of a stack
==4089== overflow in your program's main thread (unlikely but
==4089== possible), you can try to increase the size of the
==4089== main thread stack using the --main-stacksize= flag.
==4089== The main thread stack size used in this run was 8388608.
==4089==
==4089== Process terminating with default action of signal 11 (SIGSEGV)
==4089== Access not within mapped region at address 0x7FE6D7111
==4089== at 0x4A256A0: _vgnU_freeres (in /usr/lib/valgrind/vgpreload_core-amd64-linux.so)
==4089== If you believe this happened as a result of a stack
==4089== overflow in your program's main thread (unlikely but
==4089== possible), you can try to increase the size of the
==4089== main thread stack using the --main-stacksize= flag.
==4089== The main thread stack size used in this run was 8388608.
==4089==
==4089== HEAP SUMMARY:
==4089== in use at exit: 17,520 bytes in 4 blocks
==4089== total heap usage: 4 allocs, 0 frees, 17,520 bytes allocated
==4089==
==4089== LEAK SUMMARY:
==4089== definitely lost: 0 bytes in 0 blocks
==4089== indirectly lost: 0 bytes in 0 blocks
==4089== possibly lost: 0 bytes in 0 blocks
==4089== still reachable: 17,520 bytes in 4 blocks
==4089== suppressed: 0 bytes in 0 blocks
==4089== Rerun with --leak-check=full to see details of leaked memory
==4089==
==4089== For counts of detected and suppressed errors, rerun with: -v
==4089== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)
Segmentation fault (core dumped)
ifstream inputFile语句发生错误。
EDIT3:根据要求,控制台会话:
paladin@paladin:~/Programming/Contour Constructor 2/bin/Debug$ ./Contour\ Constructor\ 2
For particle type, enter 1 (e-) or 2 (p+)
Particle type: 2
Segmentation fault (core dumped)
输入文件中有1200402行,对应于PIC代码中的600200个粒子加2条描述性行。
EDIT4:在黑暗中完成镜头,但我最初是在GCC 4.4.7的Scientific Linux上编译的。我现在使用最新的Ubuntu版本(4.8.1)。在过渡期间有什么变化会导致我正在使用的文件大小无效吗?
答案 0 :(得分:6)
这里的一个重要提示是,valgrind认为你正在切换线程 - 当然,从你展示的代码来看,你并没有使用多线程。由于多线程程序中的每个线程都有自己的堆栈,因此valgrind假定如果堆栈指针的变化超过某个阈值(参见valgrind输出中提到的--max-stackframe),那么您将切换到另一个线程。
实际上,正在发生的事情是你已经创建了一个巨大的堆栈帧,确切地说是9603240字节。这超出了您可能默认获得的8MB左右。您可以通过查看shell来查看当前的软限制:
$ ulimit -s
8192
换句话说,堆栈限制为8MB。如果超过该限制,Linux将假设发生了一些错误(tm)并终止了您的过程。
您可以使用的一个即时修复是提高限制,或者只是将其设置为无限制:
$ ulimit -s 16384 # 16MB stack
$ ulimit -s unlimited # "unlimited" stack
这应该可以阻止你的进程崩溃,并解释为什么它在一个盒子而不是另一个盒子上工作正常(它工作的那个盒子可能默认设置了更高的堆栈大小限制)。
现在,从设计的角度来看,创建这么大的堆栈帧通常是一个坏主意。对于大型分配,您应该使用堆内存,例如:
double data[records];
可以替换为
double *data = new double[records];
// use data ...
delete[] data;
它分配并释放堆中的内存。这样可以让您首先避免此类问题。或者,您可以始终使用标准容器之一,例如std :: vector&lt;&gt;`来避免此问题。
答案 1 :(得分:2)
如果您仅针对较大的输入大小看到此问题,则在创建phaseSpace
时可能会出现堆栈溢出,因为这可能是一个非常大的数组。如果使用std::vector
而不是普通数组,则应避免出现此类问题:
#include <vector>
// ...
// A vector containing vectors containing integers.
// Initialized to contain the appropriate amount of space filled with zeros
std::vector< std::vector<int> > phaseSpace(pip, std::vector<int>(xip, 0));
其余的代码可能与向量的工作原理相同。
或者,如果xni
和pni
超出范围,您将覆盖随机内存。您可以添加输出语句来显示这些值,看看是否有错误。
答案 2 :(得分:0)
我很惊讶这个程序甚至编译:你声明在编译期间无法确定的大小数组,如下所示。你能说出你正在使用哪个编译器吗?
int records = dataformat[1] + 2;
double data[records];
答案 3 :(得分:0)
这可能就像使用std :: vector而不是本机数组一样。
// This program converts the column output of a 1D PIC code into a
// workable solution
#include <cmath>
#include <fstream>
#include <iostream>
#include <limits>
#include <vector>
double calculateXMaximum(const std::vector<double>& arraymax) {
double maximum = -std::numeric_limits<double>::max();
for (unsigned k = 1; k < arraymax.size()/2; ++k) {
maximum = std::max(arraymax[2*k], maximum);
}
return maximum;
}
double calculateXMinimum(const std::vector<double>& arraymin) {
double minimum = std::numeric_limits<double>::max();
for (unsigned k = 1; k < arraymin.size()/2; ++k) {
minimum = std::min(arraymin[2*k], minimum);
}
return minimum;
}
double calculatePXMaximum(const std::vector<double>& arraymax) {
double maximum = -std::numeric_limits<double>::max();
for (unsigned k = 1; k < arraymax.size()/2; ++k) {
maximum = std::max(arraymax[2*k+1], maximum);
}
return maximum;
}
double calculatePXMinimum(const std::vector<double>& arraymin) {
double minimum = std::numeric_limits<double>::max();
for (unsigned k = 1; k < arraymin.size()/2; ++k) {
minimum = std::min(arraymin[2*k+1], minimum);
}
return minimum;
}
int main()
{
// Variables settable before running program
// - will set up initialisation later.
int xni = 0;
double xntemp = 0;
int xi; // X interpolates, defined from console for resolution of diagram
int pnj = 0;
double pntemp = 0;
int pi;
int type;
// Determines momentum modifier!
std::cout << "For particle type, enter 1 (e-) or 2 (p+)\n";
std::cout << "Particle type: ";
std::cin >> type;
const double modifier = (type == 2) ? 1836.0 : 1.0;
std::ifstream inputFile("fi020000.dat");
std::ofstream outputFile("fi20k.dat");
int dataformat[2];
inputFile >> dataformat[0];
inputFile >> dataformat[1];
int records = dataformat[1] + 2;
std::vector<double> data(records, 0.0);
std::cout << "Number of particles: " << dataformat[1]/2 << std::endl;
// Introduction of data from input data file loop. Produces records.
for (int count = 0; count < records; ++count) {
inputFile >> data[count];
}
// Calling functions for xmin and xmax. May streamline later
const double xmax = calculateXMaximum(data) * 1.1;
std::cout << "Maximum x value: " << xmax << std::endl;
const double xmin = calculateXMinimum(data) * 1.1;
std::cout << "Minimum x value: " << xmin << std::endl;
const double pmax = calculatePXMaximum(data) * 1.1 / modifier;
std::cout << "Maximum p value: " << pmax << std::endl;
const double pmin = calculatePXMinimum(data) * 1.1 / modifier;
std::cout << "Minimum p value: " << pmin << std::endl;
// Definition of bin size
std::cout << "Entire desired number of x bins: ";
std::cin >> xi;
const int xip = xi;
std::cout << "Enter desired number of p bins: ";
std::cin >> pi;
const int pip = pi;
std::cout << "Grid is " << xip << " x " << pip << std::endl;
// Calculate DELTA X and DELTA P
const double deltax = (xmax - xmin)/(xip);
const double deltap = (pmax - pmin)/(pip);
std::cout << "Resolution of x: " << deltax << std::endl;
std::cout << "Resolution of p: " << deltap << std::endl;
std::vector< std::vector<int> > phaseSpace(xip, std::vector<int>(pip, 0));
for (int phasecount=1; phasecount < (records/2)-1; ++phasecount) {
xntemp = (data[2*phasecount] - xmin)/deltax;
xni = std::floor(xntemp);
pntemp = ((data[(2*phasecount)+1] / modifier) - pmin)/deltap;
pnj = std::floor(pntemp);
phaseSpace[xni][pnj] = phaseSpace[xni][pnj] + 1;
}
for (int xoutcount = 0; xoutcount < xip; ++xoutcount) {
for (int poutcount = 0; poutcount < pip; ++poutcount) {
outputFile << xmin+((xoutcount+0.5)*deltax) << " " << pmin+((poutcount+0.5)*deltap) << " " << phaseSpace[xoutcount][poutcount] << "\n";
}
outputFile << "\n";
}
std::cout << "Program complete" << std::endl;
return 0;
}
我删除了一些std::endl
调用,并将其替换为"\n"
,以避免不必要的I / O缓冲区刷新。
我对你的最小值和最大值的计算方式略有改变。
我移动了一些变量声明,并在可能的情况下使它们成为const
。
重要提示:在阅读输入时,您应该检查ifstream
的状态。就目前情况而言,你可以阅读文件末尾并且永远不会知道。似乎也存在对data
数组内容的误解。看起来好像你认为它包含两个主要的描述性行。但是,您已将这两个数字从流中提取到dataformat
,因此您无需考虑这些数字。
一小组经过手工验证的测试输入和输出数据非常有用。