views:

201

answers:

6

I'm having a tricky debugging issue, perhaps due to my lack of understanding about how c++ manages memory. The code is too long to post, but the essential setup is as follows:

global_var = 0;
int main() {
  for(i = 0; i < N; ++i) {
    ClassA a;
    new ClassB(a); // seems to be problem!
  }
}

For some N, global_var gets corrupted (is no longer 0). There is nothing in the constructors of ClassA or ClassB that mess with global_var.

Replacing new ClassB(a) with ClassB b(a) seems to solve the problem, although this doesn't allow me to do what I want (create a boost::ptr_vector with the new ClassB(a) instances).

Any ideas on what might be going wrong?

Update: I'm really doing something like:

global_var = 0;
int main() {
  boost::ptr_vector<ClassB> myobjects;
  for(i = 0; i < N; ++i) {
    ClassA a;
    myobjects.push_back(new ClassB(a)); // seems to be problem!
  }
}

Both create problems. But why is this a problem? Should I be doing something else to put a bunch of objects into a queue? I'm using myobjects it as the basis of a Command Pattern.

Update

`classB' looks like:

class ClassB {
public:
  ClassB() {}
  ClassB(ClassA a) : a_(a) {}
private:
  ClassA a_;
}

ClassA is just a simple list initialization as well (in real life).

Problem?

Update I believe this may have something to do with the fact that global_var is actually a complex matrix type and there may be issues with the way it allocates memory.

+2  A: 

Memory in C++ is not automatically freed by default. The result of

  new ClassB(a); // seems to be problem!

is being created on the heap. The address of the memory is not assigned to anything. Therefore one can't manually delete it like

  ClassB* b = new ClassB(a); // creates a B, returns an address,
                             // and stores the address in b.
  delete b;       // deletes memory at address "b"

The failure to delete the memory may cause the heap to overflow into other regions of memory in your program, causing your global variable to be overwritten. This could happen without assigning the result of new to a variable, so long as its not deleted.

Doug T.
A reasonable memory allocator will fail instead of clobbering non heap memory.
Captain Segfault
I doubt it would corrupt a global variable (as they usually aren't on the heap), though I may be wrong.
Gab Royer
I find that hard to believe. new() would start to throw bad_alloc if it runs out of memory not start clobbering the address space reserved by globals.
Martin York
A: 

This is most probably a bug in one of the two constructors (ClassA or ClassB) which is overwriting the memory of global_var, or corrupting some other memory which eventually causes it to get overwritten.

Captain Segfault
My constructors are very simple. The only thing I'm doing really is copying a into ClassB. Basically I'm taking a command (Class A) and attaching it to a specific type of executor (Class B).
Tristan
+1  A: 

Does classA have a copy constructor? If so, what does it look like? If not, create a copy constructor in classA and see if that fixes the problem.

Other than that, try running your code in a debugger and see if you can pin-point when that global changes.

Mark Jones
A: 

I'd suspect something in Class A's copy constructor.

markh44
A: 

You can set a data write breakpoint on global_var to find out where it's being written.

In the MSVC debugger, set a breakpoint on the 'for' line. When it gets there, select "New Breakpoint->New Data Breakpoint..." from the Debug menu and enter the &global_var. Continue. The debugger will break the next time the variable is written.

gdb can do this too, but I've forgotten the syntax.

Jesse Hall
A: 

After much exploration, this behavior turned out to be due to a bug in the underlying class of global_var. There was a subtle bug in the way global and static memory allocation was being done.

Tristan