【问题标题】:Unable to print out C++ obj member variable无法打印出 C++ obj 成员变量
【发布时间】:2014-11-13 23:21:50
【问题描述】:

我正在尝试学习一些 OOP 实践,同时为我的研究开发模型。我似乎遇到了一些我不确定是否属于我正在使用的书的范围的问题,Stephen Prata 的 C++ Primer。

现在,我正在尝试开发一个名为 StochasticModel 的对象。这个 SM 对象应该能够接受另一个名为 LengthDistribution 的对象并在其上运行模拟。我目前正在使用以下伪代码为这种类型的交互设置框架。需要注意的是,我将类定义组合在一起,因为我最初将它们分别放在两个文件中。您还会在其中看到一些 CudaMallocManaged(),因为我也打算在 GPU 上使用这些对象,但 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.

}

我的长度分布类。

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);
  }
};

最终结果是应用程序在运行后“已停止工作”。它编译得很好,但是当它遇到 state

【问题讨论】:

  • 您的实际编译器错误消息/运行时异常是什么。我无法从您的问题中得到线索,那么我们应该如何提供帮助? (所有这些“blah blah”代码应该做什么,无助于诊断您的实际问题)
  • 在极少数情况下,您希望实际重载 newdelete 运算符……您确定要这样做吗?
  • new 和 delete 运算符的重载是为使用 Cuda Unified Memory 做准备,很遗憾,我认为我需要它。如果这真的是个问题,那么我也许可以将其移除并制作一个纯粹基于 CPU 的模型。

标签: c++


【解决方案1】:

在您的构造函数中,您创建了一个隐藏成员变量state 的新局部变量。这会导致成员变量未定义,稍后在您尝试访问它时会导致崩溃。

您应该更喜欢使用初始化列表:

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

【讨论】:

  • 哦,好的。我现在可以看到了。让我试试这个解决方法。
  • 太棒了,谢谢,解释得很清楚。我想我很困惑,因为我认为每当我在类方法中对成员变量进行操作时,对对象的存储版本的成员变量进行操作就足够聪明了。但是,在我看来,如果我完成了“state = new LengthDistribution(*LD))”并省略了类型,我可能没有创建成员变量的新本地版本,而是在所需版本上进行操作。我理解的对吗?
  • @KarstenChu,是的,完全正确。但这是一个容易犯的错误,因为在初始化变量时声明变量只是一种习惯。通过使用初始化程序,您不会遇到这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-18
  • 1970-01-01
  • 2017-11-08
  • 1970-01-01
  • 2020-10-18
  • 1970-01-01
相关资源
最近更新 更多