Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: How is it possible that reading data can affect memory?

I've been going deeper into C++ recently and my bugs seem to get complex.

I have a vector of objects, each object contains a vector of floats. I decided I needed to create a further flat array containing all the float values of all objects in one. It's a little more complex than that but the gist of the problem is that as I loop through my objects extracting the float values, at some point my vector of objects is changed, or corrupted in some strange way. (My read operations are all const functions)

Another example was with MPI. I was just getting started so I just wanted to run the exact same code on two different nodes with their own memory and with no data transfer happening, all very simple. To my surprise I got segmentation errors and after hours tracking, I found that one assignment of one variable was setting an entirely different variable to NULL.

So I am curious, how is it possible that read operations can affect my data structures. Similarly how can a seemingly unrelated operation affect another. I couldn't expect solutions to my problems with those brief descriptions but any advice will be greatly appreciated.

Update: Here's a segment of the code, I didn't post originally because I am not sure how much can be extracted from it without understanding the whole system.

One thing I just found out though was that when I stopped assigning the value to my flat array and just cout'ed instead, the seg errors disappeared. So perhaps I am declaring my array wrong, but even if I was I'm not sure how it would affect the object vector.

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

my flat array is a member function

float * flatFitness;

initailsed in the constructor like so:

flatFitness = new float(popSize);

Update 2:

I just want to point out that the two examples above are not related, the first one is not multi threaded. The second MPI example is technically, but MPI is distributed memory and I deliberately attempted the most simple implementation I could think of, which is both machines running code independently. There is however one extra detail, I put in a condtional saying

if node 1 then do bottom half of loop

if node 1 then do top half

Again the memory should be isolated, they should be working as if they know nothing about each other.. but removing this conditional and making both loops do all cubes, eliminates the error

like image 801
zenna Avatar asked Apr 27 '09 22:04

zenna


1 Answers

This is not an array constructor:

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

You're creating one float on the heap here, initialized with value popSize. If you want an array of floats you need to use brackets instead of parentheses:

float *flatFitness = new float[popSize];

This could easily be causing the problems you describe. Also, remember when you create arrays, you need to delete using delete [] (eventually):

delete [] flatFitness;

If you just use delete, it might work, but the behavior is undefined.

If you want to avoid using array syntax altogether, why not use std::vector? You can create a vector of popSize elements like this:

#include <vector>

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

This will be freed automatically when it falls out of scope, so you don't have to worry about new or delete.

Update (re: comment): If you're already using std::vectors elsewhere in your code, take a look at std::vector::swap(). You may be able to avoid copying things altogether and just swap a couple vectors back and forth between buffering for CUDA and the processing you're doing here.

like image 146
Todd Gamblin Avatar answered Sep 29 '22 23:09

Todd Gamblin