2013-09-12 3 views
3

У меня была рабочая программа для анализа данных на C++, которая дала на сегодняшний день что-то вроде 35 успешных файлов данных. Я работал над Scientific Linux в Code: Blocks, когда он работал, и за исключением небольших ошибок с очень большими размерами сетки (1000x1000 +), он отлично работал и производил именно то, что я искал.Сегментация Fault 139 (core dumped) C++ после смены операционной системы

Я недавно перешел на 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++ менее месяца назад. Таким образом, я понятия не имею, что происходит. Я знаю, что эта тема много видела, но я не могу понять совет.

EDIT: Стек след:

#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 заявлении файл_ввода.

EDIT3: В соответствии с просьбой, сеанс консоли:

[email protected]:~/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 строки входного файла, соответствующая 600200 частиц в коде ПОС плюс 2 описательной линии.

EDIT4: Полный снимок в темноте, но я изначально был скомпилирован под GCC 4.4.7 на Scientific Linux. Теперь я использую последнюю версию Ubuntu (4.8.1). Что-то изменилось в промежутке времени, что приведет к аннулированию размера файла, который я использую?

+0

'gdb --args prog arg arg' then' r' для запуска. Когда возникает ошибка, 'bt' для трассировки стека.(Так как ядро ​​было сброшено, вы также можете загрузить p этим изображением с помощью 'gdb', затем выпустить' bt'.) – ikegami

+5

(«segfault 139» избыточно. 139 = 11 | 128 = segfault и core dumped.) – ikegami

+2

Вы перекомпилировали Ubuntu? – trojanfoe

ответ

0

Я удивлен, что эта программа даже компилирует: вы объявляете массивы размера, которые не могут быть определены во время компиляции, например, ниже. Не могли бы вы сказать, какой компилятор вы используете?

int records = dataformat[1] + 2; 
double data[records]; 
+0

GCC поддерживает этот вид использования. Не помню, как они называют эту функцию. –

+3

@AdamBurry "Array russian roulette"? –

+0

@ DanielDaranas, http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html –

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 выходят за пределы, вы перезаписать оперативную память. Вы можете добавить выходные инструкции, чтобы показать эти значения и посмотреть, что-то не так.

+0

Итак, это объясняет, почему оно иногда используется для возврата -1 и сбоя для очень больших размеров массива. Стоит в том числе, что в любом случае, чем выше размер массива, тем лучше разрешение контурной диаграммы. К сожалению, я думаю, что эта авария происходит раньше, но я все равно изменю, так как это будет полезно. Спасибо :) –

+0

@NicholasMillington, вы также должны использовать std :: vector для вашего массива данных. std :: vector выделяет кучу, тогда как массивы, которые вы в настоящее время используете, выделяют в стеке. Существует больше кучи, чем стек. Кроме того, вы должны указать емкость векторов при их создании, чтобы избежать дорогостоящих операций изменения размера. –

+0

Большое спасибо. Я выберу это завтра утром. –

6

Большой намек на то, что valgrind думает, что вы переключаете потоки - и, конечно, из кода, который вы показали, вы не используете несколько потоков. Поскольку каждый поток в многопоточной программе имеет свой собственный стек, valgrind предполагает, что если указатель стека изменяется более чем на определенный порог (см. --max-stackframe, как указано в выводе valgrind), что вы переключаетесь на другой поток.

В действительности, что происходит, вы создали HUGE стек кадров, 9603240 байт, если быть точным. Это превышает 8 МБ или около того, что вы, вероятно, получаете по умолчанию. Вы можете увидеть текущий мягкий предел, посмотрев в оболочку:

$ ulimit -s 
8192 

Другими словами, стек ограничивается 8 МБ. Если вы превысите этот предел, 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 <> `, чтобы избежать проблемы.

+0

Большое спасибо - я еще не смог переписать программу в векторную форму (сделаю это позже), поэтому это немедленное исправление было очень полезно. –

+0

Я реализовал XDEBUG на HHVM и сохранил эту ошибку дампа ядра в своем ящике Linux Mint, когда я включил отладчик. Спасибо!!! Эта настройка изменила проблему. Я не ожидал поиска ошибки в массивной кодовой базе HHVM. – RyanNerd

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, поэтому вам не нужно их учитывать.

Очень маленький набор проверенных вручную тестовых входных и выходных данных будет полезен.

Смежные вопросы