C ++:读取数据如何影响内存?

时间:2009-04-27 22:14:31

标签: c++ mpi corruption

我最近一直在深入研究C ++,我的错误似乎变得复杂。

我有一个对象向量,每个对象都包含一个浮点向量。我决定创建一个包含所有对象的所有浮点值的平面数组。它比这复杂一点,但问题的关键在于,当我遍历我的对象提取浮点值时,在某些时候我的对象向量被改变,或以某种奇怪的方式被破坏。 (我的读操作都是const函数)

另一个例子是MPI。我刚刚开始,所以我只想在两个不同的节点上使用自己的内存运行完全相同的代码,并且不会发生数据传输,这一切都非常简单。令我惊讶的是,我得到了分段错误,经过几小时的跟踪,我发现一个变量的一个赋值就是将一个完全不同的变量设置为NULL。

所以我很好奇,读操作如何影响我的数据结构。同样,看似无关的操作如何影响另一个。我不能指望用这些简短的描述解决我的问题,但任何建议将不胜感激。

更新: 这是代码的一部分,我最初没有发布,因为我不确定在不了解整个系统的情况下可以从中提取多少。

我刚发现的一件事是,当我停止将值分配给我的平面阵列而只是cout'ed时,seg错误消失了。所以也许我声明我的数组是错误的,但即使我是,我也不确定它会如何影响对象向量。

void xlMasterSlaveGpuEA::FillFlatGenes() {
    int stringLength = pop->GetGenome(0).GetLength();
    for (int i=0;i<pop->GetPopSize();i++)
        for (int j=0;j<stringLength;j++)
            flatGenes[(i*stringLength)+j]<< pop->GetGenome(i).GetFloatGene(j);
}

float xlVectorGenome::GetFloatGene(unsigned int i) const {
    return GetGene(i);
}

我的平面数组是一个成员函数

float * flatFitness;

在构造函数中启动,如下所示:

flatFitness = new float(popSize);

更新2:

我只想指出上面两个例子没有关系,第一个不是多线程的。第二个MPI示例在技术上,但MPI是分布式内存,我故意尝试了我能想到的最简单的实现,这是两台机器独立运行代码。然而,有一个额外的细节,我提出了一个条件性的说法

if node 1 then do bottom half of loop

if node 1 then do top half

同样,内存应该被隔离,它们应该像对彼此一无所知那样工作..但是删除这个条件并使两个循环都能完成所有多维数据集,消除了错误

3 个答案:

答案 0 :(得分:14)

这不是数组构造函数:

float * flatFitness;
flatFitness = new float(popSize);

您在此处在堆上创建一个浮点数,使用值popSize初始化。如果你想要一个浮点数组,你需要使用括号而不是括号:

float *flatFitness = new float[popSize];

这很容易导致您描述的问题。另外,请记住在创建数组时,需要使用delete [](最终)删除:

delete [] flatFitness;

如果您只使用delete,它可能会起作用,但行为未定义。

如果您想完全避免使用数组语法,为什么不使用std::vector?您可以创建一个popSize元素的向量,如下所示:

#include <vector>

std::vector<float> flatFitness(popSize);

当它超出范围时会自动释放,因此您不必担心newdelete

更新(重新:评论):如果您已在代码中的其他位置使用std::vectors,请查看std::vector::swap()。您可以完全避免复制事物,只需在缓冲CUDA和您在此处进行的处理之间来回交换几个向量。

答案 1 :(得分:0)

我怀疑你有多线程或内存损坏问题,你不知道。您描述的行为不是任何标准的,按设计的,理想的行为。

答案 2 :(得分:-1)

jeffamaphone可能是正确的,这是一个线程问题。另一种可能性是您正在阅读的对象已被删除。然后,您将从无效的地址中读取。您此时写入的数据结构也可能存储在以前占用的向量的相同位置。这将导致您描述的行为。

编辑(根据您的更新):

这可能有问题:stringLength在外部循环之外被初始化,但看起来它需要在外部循环期间更新:

int stringLength = pop->GetGenome(0).GetLength();
for (int i=0;i<pop->GetPopSize();i++)
    for (int j=0;j<stringLength;j++)
        flatGenes[(i*stringLength)+j]<< pop->GetGenome(i).GetFloatGene(j);

建议修复:

for (int i=0;i<pop->GetPopSize();i++) {
    int stringLength = pop->GetGenome(i).GetLength();
    for (int j=0;j<stringLength;j++) {
        flatGenes[(i*stringLength)+j]<< pop->GetGenome(i).GetFloatGene(j);
    }
}