2013-10-27 5 views
0

У меня есть программа, которая, как предполагается, вычисляет траекторию маятника с методом четвертого порядка рут-кутты и методом эйлера-кромера ... У меня есть segfault.Сегментация Неисправность из-за векторов

Я понятия не имею, как это исправить, так как вы можете видеть, что у меня есть несколько std :: cout для попытки отладки, но они даже не выводятся. Это заставляет меня полагать, что функция никогда не делает это для выполнения main();

Моя текущая интуиция говорит, что она ошибочна во время деклараций функции, но если я ошибаюсь, я хотел бы знать. Если это вообще возможно, можете ли вы описать методы, которые вы использовали для отладки?

#include <iostream> 
#include <cmath> 
#include <string> 
#include <vector> 
#include <stdlib.h> 
#include <fstream> 

#define N 1 

// Pendulum Variables 
double d_pendLength = 1.0, d_pendMass = 1.0; // Pendulum Properties 
double d_viscParam = 1.0, d_gravity = 1.0; //9.80665; // Enviromental Factors 
double d_dAmp = 0.0, d_dFreq = 0.0; // Driving Force 

double d_initTheta = 0.0, d_initAVel = 0.0; //Initial Conditions 

void v_rungekutta(double d_time, std::vector<double> d_pendulum, double d_step); 
void v_eulercromer(double d_time, std::vector<double> d_pendulum, double d_step); 
double d_derivative(double d_time, std::vector<double> d_pendulum, int i_de); 

int main(void) 
{ 
    // Numerical Variables 
    double d_step = 0.01, d_mTime = -1, d_mPeriod = 300; 

    // Global Variables 
    double d_time = 0.0, d_period = 0.0, d_limit; 

    // Function Vectors 
    std::vector<double> d_pendulum (2); 

    // Settings 
    std::string plot = "theta", algo = "rk4"; 


    std::cout << "START!"; 
    std::ofstream file_output; 
    std::cout << "HAIDATA!"; 
    file_output.open("pendulum.data"); 

    std::cout << "HAI!"; 
    d_pendulum.at(0)= d_initTheta; //Initial Theta 
    d_pendulum.at(1)= d_initAVel; //Initial Omega 
    std::cout <<"BAI!"; 

    if (d_mPeriod > 0) 
    { 
     d_limit = d_mPeriod; 
    } 
    else if (d_mTime > 0) 
    { 
     d_limit = d_mTime; 
    } 
    else 
    { 
     std::cout << "No Limit Specified"; 
     exit(1); 
    } 

    for (int i_currentStep=1; i_currentStep*d_step<=d_limit;i_currentStep++)  
    { 
     d_time = i_currentStep*d_step; 

     if (algo == "rk4") 
     { 
      v_rungekutta(d_time, d_pendulum, d_step); 
     } 
     else if (algo == "ec") 
     { 
      v_eulercromer(d_time, d_pendulum, d_step); 
     } 
     file_output << d_time << d_pendulum.at(0) << d_pendulum.at(1) << std::endl; 
    } 


    file_output.close(); 
    d_pendulum.clear(); 

    return 0; 
} 


void v_rungekutta(double d_time, std::vector<double> d_pendulum, double d_step) 
{ 
    double h=d_step/2.0; 
    std::vector<double> t1, t2, t3, k1, k2, k3, k4; 
    int i; 

    for (i=N;i>0;i--) t1[i]=d_pendulum.at(i)+0.5*(k1[i]=d_step*d_derivative(d_time, d_pendulum, i)); 
    for (i=N;i>0;i--) t2[i]=d_pendulum.at(i)+0.5*(k2[i]=d_step*d_derivative(d_time+h, t1, i)); 
    for (i=N;i>0;i--) t3[i]=d_pendulum.at(i)+ (k3[i]=d_step*d_derivative(d_time+h, t2, i)); 
    for (i=N;i>0;i--) k4[i]=d_step*d_derivative(d_time+d_step, t3, i); 

    for (i=N;i>0;i--) d_pendulum.at(i) += (k1[i]+2*k2[i]+2*k3[i]+k4[i])/6.0; 
} 

void v_eulercromer(double d_time, std::vector<double> d_pendulum, double d_step) 
{ 
    int i; 
    for (i=N;i>0;i--) d_pendulum.at(i) += d_derivative(d_time, d_pendulum, i)*d_step; 
} 

double d_derivative(double d_time, std::vector<double> d_pendulum, int i_de) 
{ 
    double dtheta = d_pendulum.at(1); 
    if (i_de==0) return dtheta; 
    double domega = d_pendulum.at(1)+((-d_gravity/d_pendLength)*sin(d_pendulum.at(0)))+(-d_viscParam*(d_pendulum.at(1)))+(d_dAmp*sin(d_dFreq*d_time)); 
    if (i_de==1) return domega; 
    if (i_de < 0) return 0; // 0 is a possible value, exit with exit func. 
} 

РЕШЕНИЕ

Моя проблема заключалась в том, что я не был должным образом доступ векторов в rungekutta и я не дал им стартовый размер.

Перед

void v_rungekutta(double d_time, std::vector<double> d_pendulum, double d_step) 
    { 
     double h=d_step/2.0; 
     std::vector<double> t1, t2, t3, k1, k2, k3, k4; 
     int i; 

     for (i=N;i>0;i--) t1[i]=d_pendulum.at(i)+0.5*(k1[i]=d_step*d_derivative(d_time, d_pendulum, i)); 
     for (i=N;i>0;i--) t2[i]=d_pendulum.at(i)+0.5*(k2[i]=d_step*d_derivative(d_time+h, t1, i)); 
     for (i=N;i>0;i--) t3[i]=d_pendulum.at(i)+ (k3[i]=d_step*d_derivative(d_time+h, t2, i)); 
     for (i=N;i>0;i--) k4[i]=d_step*d_derivative(d_time+d_step, t3, i); 

     for (i=N;i>0;i--) d_pendulum.at(i) += (k1[i]+2*k2[i]+2*k3[i]+k4[i])/6.0; 
    } 

После:

void v_rungekutta(double d_time, std::vector<double> d_pendulum, double d_step) 
    { 
     double h=d_step/2.0; 
     std::vector<double> t1 (2), t2 (2), t3 (2), k1 (2), k2 (2), k3 (2), k4 (2); 
     int i; 

     for (i=N;i>0;i--) t1.at(i)=d_pendulum.at(i)+0.5*(k1.at(i)=d_step*d_derivative(d_time, d_pendulum, i)); 
     for (i=N;i>0;i--) t2.at(i)=d_pendulum.at(i)+0.5*(k2.at(i)=d_step*d_derivative(d_time+h, t1, i)); 
     for (i=N;i>0;i--) t3.at(i)=d_pendulum.at(i)+ (k3.at(i)=d_step*d_derivative(d_time+h, t2, i)); 
     for (i=N;i>0;i--) k4.at(i)=d_step*d_derivative(d_time+d_step, t3, i); 

     for (i=N;i>0;i--) d_pendulum.at(i) += (k1[i]+2*k2[i]+2*k3[i]+k4[i])/6.0; 
    } 
+2

Попробуйте отладчик, такой как gdb, lldb или тот, что в Visual Studio. Время, потраченное на их обучение, хорошо потрачено. –

+0

Кстати, объявления функций не выполняются. Компилятор создаст исполняемый файл, который запускается в начале вашей функции 'main()' (возможно, с некоторой статической инициализацией заранее). – user1118321

+0

Я запускаю дистрибутив Linux, поэтому я использовал gdb. Я узнал, что я не использовал .at (i) на некоторых массивах, и что я не дал ни одного размера. Большое спасибо! – NictraSavios

ответ

1

Что я могу видеть, на первый взгляд, является то, что вы пытаетесь получить доступ к элементам в пустых векторов. Попробуйте заменить [] операторами на метод at(). Разница в том, что первое не проверяет границы с возможностью создания segfault, тогда как последнее делает, бросая исключение, если индекс выходит за пределы.

+1

Как я поймаю такое исключение? – NictraSavios

+0

без ответа на вопрос @ NictraSavios, это всего лишь половина ответа. – dbliss

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