views:

307

answers:

2

Hi,

I have a class A as follows:

class A
{
public:    
    A()
    {        
        printf("A constructed\n");        
    }
    ~A();
    //no other constructors/assignment operators    
}

I have the following elsewhere

A * _a;

I initalize it with:

int count = ...
...
_a = new A[count];

and I access it with

int key = ....
...
A *a_inst = &(_a[key]);
....

It runs normally, and the printf in the constructor is executed, and all the fields in A are fine.

I ran Valgrind with the following args:

valgrind --leak-check=full --show-reachable=yes --track-origins=yes -v ./A_app

and Valgrind keeps yelling about

Conditional jump or move depends on uninitialised value(s)

and then the stack trace to the accessors statements.

Can anyone explain why this is happening? Specifically if what Valgrind says is true, why is the constructor executed?

+2  A: 

Edit: Try setting A *a = 0;

Running your code in an a simplified scenario does not produce any warnings from Valgrind. Consider the following code:

#include <iostream>

class A
{
    public:
        A()   
        {     
            std::cout << "A" << std::endl;
        }     
};

int main()
{
    A *a; 
    int count = 10; 
    a = new A[count];

    int key = 1;
    A *inst = &(a[key]);

    return 0;
}

Compiled with:

$ g++ -g main.cc -o main

and run with:

$ valgrind --leak-check=full --show-reachable=yes --track-origins=yes ./main

So, I think more information is needed. You are likely doing something between defining _a and actually allocating memory on the heap. Might I simply suggest that you merge the definition and allocation into one line?

    int count = 10; 
    A *a = new A[count];
carl
You need --leak-check=full --show-reachable=yes --track-origins=yes -v
jameszhao00
Still no warnings on my system :)
carl
Hmm weird... but the stuff I have above is the correct initialization right?
jameszhao00
Looks good to me. I think the simple way to shut up Valgrind is to allocate right away. Is there a reason why you are deferring allocation?
carl
Yea it's a class member. Can't allocate directly.
jameszhao00
I can only blindly guess at this point, but perhaps initialising to 0 will either reveal the problem or fix it: A *a = 0;
carl
Setting it to 0 didn't work.
jameszhao00
+3  A: 

This can mean that key or count contains an uninitialized value. Even if you do initialize it in the declaration, e.g. int key = foo + bar;, it could be that either foo or bar is uninitialized, and valgrind carries this over to key.

mark4o
Thanks for that tip. While I'm checking through the code, is there a valgrind option that shows those details?
jameszhao00
Since you are using --track-origins=yes it should tell you the origin of the uninitialized value in the next message.
mark4o
It says the array is uninitialized.
jameszhao00
Ah this is interesting. The line number for the actual error is when I use a class member of the object after using the accessor to get the object.
jameszhao00