2014-11-13 1 views
-1

Я пытаюсь изучить некоторые методы ООП при разработке модели для моих исследований. Кажется, я сталкиваюсь с несколькими проблемами, которые я действительно не уверен в том, что касается той книги, которую я использую, C++ Primer от Stephen Prata.Невозможно распечатать переменную-член класса C++

Прямо сейчас, я пытаюсь разработать объект, называемый StochasticModel. Этот объект SM должен иметь возможность принимать другой объект с именем LengthDistribution и запускать симуляцию на нем. В настоящее время я настраиваю рамки для этого типа взаимодействия со следующим псевдокодом. Как предостережение, я объединил определения классов, поскольку я изначально имел их в двух файлах каждый. Вы также увидите некоторые CudaMallocManaged(), поскольку я намерен использовать эти объекты на графическом процессоре, но CUDA здесь не проблема.

int main() 
{ 

//Read initial conditions, maxlength, maxiterations from input 

//Create a length distribution object from IC's and length 
LengthDistribution* LD = new LengthDistribution(initialconditions, maxlength) 

//Create a model object to operate on LD maxiterations number of times. 
StochasticModel* SM = new StochasticModel(LD, maxiterations) 

//Test that I've created an LD object as I expected by printing its values out. 
LD -> h_printToScreen(); //<- Works fine! 

//Test that model has a correct version of LD by printing LD's information to screen through 
//SM's print to screen function. 
SM->printToScreen(); //<- But when I have an object that contains the object call a function that calls its function (inception), memory access violations occur. 

} 

My Length Distribution class.

class LengthDistribution : public Managed 
{ 
private: 
    int m_maxlength; 
    int* m_lengthDistribution; 

public: 
    //User defined constructor. 
    LengthDistribution(int* initialconditions, int maxlength) 
    { 
    m_maxlength = maxlength; 
    m_lengthDistribution = new int[maxlength]; 
    m_lengthDistribution = initialconditions; 
    } 

    //Default constructor 
    //Default destructor 
    //Unified memory copy constructor allows pass-by-value 
    LengthDistribution::LengthDistribution(const LengthDistribution &LD) 
    { 
    //Copy maxlength to new state. 
    m_maxlength = LD.m_maxlength; 

    //Allocate CUDA Managed memory for lengthDistribution array 
    cudaMallocManaged(&m_lengthDistribution, m_maxlength); 

    //Copy array to new state. 
    memcpy(m_lengthDistribution, LD.m_lengthDistribution, m_maxlength); 

    } 
    __host__ void h_printToScreen() 
    { 
     printf("Host maxlength: "); 
     std::cout<<m_maxlength; 
     std::cout<<"\n"; 
     printf("Host length distribution: "); 
     for (int i = 0; i < m_maxlength; i++) 
      std::cout<<m_lengthDistribution[i]; 
     printf("\n"); 
    } 

} 

Мой Стохастический класс Модель

class StochasticModel : public Managed 
{ 

private : 
    int m_numberOfIterations; 
    LengthDistribution* state; 

public: 
    //User defined constructor 
    StochasticModel(LengthDistribution* LD, int numberOfIterations) 
    { 
     //Copy desired number of iterations. 
     m_numberOfIterations = numberOfIterations; 

     //Assign LD to SM's state variable. I think I'm having an issue here. 
     //Copy LD into SM object's state variable. 
     LengthDistribution* state = new LengthDistribution(*LD); 
    } 

    //User defined copy constructor 
    Stochastic::Model(const StochasticModel &SM) 
    { 
     m_numberOfIterations = SM.m_numberOfIterations; 
     cudaMallocManaged(&state, sizeof(SM.state)); 
     state = new LengthDistribution(*SM.state); 
     //memcpy(state, SM.state, sizeof(state)); 
    } 

    //Print out member length distribution's values. 
    printToScreen() 
    { 
    state->h_printToScreen(); //When I trace the debugger through here, it triggers an access violation when trying to print out the state's array. 
    } 
} 

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

class Managed { 
public: 
    void *operator new(size_t len) { 
    void *ptr; 
    cudaMallocManaged(&ptr, len); 
    return ptr; 
    } 

    void operator delete(void *ptr) { 
    cudaFree(ptr); 
    } 
}; 

Конечные результаты состоят в том, что приложение после запуска «перестало работать». Он компилируется отлично, но когда он попадает на ошибку доступа к памяти для состояния < -printToScreen, он «перестает работать». Пройдя через отладчик, он говорит, что массив, который он пытается распечатать для объекта LD и целого, не определен. Я чувствую, что мне не хватает чего-то элементарного здесь, но я хотел бы иметь возможность использовать объект SM для манипулирования и отображения информации из объекта LD.

+0

И то, что фактическая ошибка компилятора исключение сообщения/выполнения. Я не могу получить ключ от вашего вопроса, так как мы должны помочь? (все это _ «бла-бла», что должен делать код, не помогает диагностировать вашу реальную проблему) –

+0

Очень мало ситуаций, когда вы хотите фактически перегрузить операторы 'new' и' delete' ... Вы уверены, что это то, что вы хотите сделать? – Rufflewind

+0

Перегрузка новых и удаленных операторов готовится к использованию единой памяти Cuda, так что, к сожалению, мне кажется, что она мне нужна. Если это действительно проблема, я мог бы удалить ее и создать чистую модель на базе процессора. –

ответ

2

В вашем конструкторе вы создали новую локальную переменную, которая скрывает переменную-член state. Это оставляет переменную-член неопределенной, что приводит к сбою позже, когда вы пытаетесь получить к ней доступ.

Вы должны предпочесть использовать список инициализации вместо:

StochasticModel(LengthDistribution* LD, int numberOfIterations) : 
    m_numberOfIterations(numberOfIterations), 
    state(new LengthDistribution(*LD)) 
{ 
} 
+1

О, хорошо. Я вижу это сейчас. Позвольте мне попробовать это исправить. –

+0

Удивительно, спасибо, это было очень четкое объяснение. Я думаю, я был в замешательстве, потому что думал, что в любое время, когда я работал с переменной-членом в методе класса, он был достаточно умен, чтобы работать с хранимой версией этого элемента переменной-объекта. Однако мне кажется, что если бы я сделал «state = new LengthDistribution (* LD))» и оставил этот тип, я, возможно, не создал новую локальную версию переменной-члена и вместо этого работал с нужной версией. Правильно ли я понимаю это? –

+1

@ KarstenChu, да, это точно. Но это легко сделать, потому что это просто привычка объявлять переменную при ее инициализации. Используя инициализатор, вы не можете решить эту проблему. –

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