1

I want to write some unit tests of a library I'm writing

I have a class which looks like this one :

class A
{
public:
    A(B* pB)
    // construction details, involves my library
    // but ultimately there is a new being done ,)

    B* m_pB;
};

I'd like to check that the pointer m_pB is actually initialized, so I did something along these lines :

A* p = // creation of this object involves my library
BOOST_REQUIRE( p->m_pB != NULL );

but it happens g++ does not zero-initialize the memory, so the value of p->m_pB is just plain random. Is there a way to force g++ to zero initialize this memory for me when I new the object?

I believe Visual Studio does something similar with specific codes dependeing on where the memory is allocated.

edit: I can think of 2 backup solutions right now: using a smart pointer, or writing a new operator ...

foke
  • 1,339
  • 2
  • 12
  • 20
  • 6
    Why don't you want to initialize m_pB to zero in the class constructor? – Julio Gorgé Jul 18 '11 at 20:49
  • 5
    Er, what do you want to check, exactly? Your ctor should take care of all member initialisation — you want zero, put zero in there. – Cat Plus Plus Jul 18 '11 at 20:49
  • Do you want the pointer to default to something or the memory the pointer points to? It's not clear from your question ... – celavek Jul 18 '11 at 20:52
  • what do you want zero initialized? the pointer m_pB, or the object that the pointer points to? if its the pointer, how can it be zero initialized if it is a required parameter of the constructor? in this design, it is your responsibility to ensure that the pointer is NULL or not NULL... – J T Jul 18 '11 at 20:52
  • See here: [new and parentheses][1] [1]: http://stackoverflow.com/questions/620137/do-the-parentheses-after-the-type-name-make-a-difference-with-new It may help – James Jul 18 '11 at 20:54
  • the pointer itself. It could be forgotten in the constructor for instance, but more specifically, the library does dependency injection and B is a dependency, and a bug could result in m_b not being initialized – foke Jul 18 '11 at 20:56
  • 2
    so implement the default constructor: "A() : m_pB(NULL) {}" – J T Jul 18 '11 at 20:58
  • If everything fails (which I doubt will happen) and all you want to check is if the pointer is initialized I guess you could try the GNU debugger (gdb). – E.O. Jul 18 '11 at 21:07

4 Answers4

9

Simply implement the default constructor. This guarantees that without passing an argument, the pointer is initialized to NULL.

class A
{
public:
    A(B* pB)
    // construction details, involves my library
    // but ultimately there is a new being done ,)

    A() : m_pB(NULL) {}

    B* m_pB;
};

Or as Fritschy points out:

A() : m_pB() {}
J T
  • 4,946
  • 5
  • 28
  • 38
5

Use an always-initializing class.

template<typename T> class always_initialized {
    T t;
public:
    operator T&() { return t; }
    operator const T&() const { return t; }
    always_initialized() : t() {}
    always_initialized(const T& ref) : t(ref) {}
};

Edit: I see that most people didn't understand what this actually does. If you just set the pointer to NULL, then you have to do that separately in every constructor, and then you have to do that again for every variable, and it's also not generic for other POD things like POD structs. always_initialized is more maintainable, as you're not repeating yourself, more concise, and more generic, as it's good for any POD type or even non-POD type.

Puppy
  • 144,682
  • 38
  • 256
  • 465
3

Did you consider making m_pB private and always initializing it in your constructors? By using encapsulation to enforce your class invariants you don't even need to do the kinds of checks you're implementing here.

Mark B
  • 95,107
  • 10
  • 109
  • 188
-2

Thanks for your answers, but I'd like a less invasive technique, as the classes are part of the test, and their constructor is right in the midle of the subject which is dependency injection.

I was just hopping for something similar to visual studio which sets the memory to some specific value in debug mode (I think?), through an option of g++ or something alike.

some answers/comments basically fall back to saying "don't test it, just don't make the mistake"

Finally, I've overloaded the new operator and added a call to memset(ptr, 0, size); and I get my critical check p->m_pB != __null failed, it works fine.

you all get a +1 anyway, especially DeadMg for the interesting solution

foke
  • 1,339
  • 2
  • 12
  • 20
  • That only works for dynamically allocated objects, because `operator new` won't be called if you put an `A` on the stack. – fredoverflow Jul 19 '11 at 08:57
  • isn't the point of unit tests to find problems with your code? I'd say you just found your first one. the solution isnt to overload the new operator, but to simply fix your code!!!! I suggest you look up "C++ initializer list", you need to learn what these are going forward. – J T Jul 19 '11 at 13:58
  • @Fred my objects are all dynamically allocated @J T thank you but I know how to fix this 'problem' I don't need your help, I also know what initializer lists are. All I asked was "Is there a way to force g++ to zero initialize this memory for me when I new the object?" – foke Jul 19 '11 at 19:22
  • @foke: the answer is 'yes' to your question, and its done by using a constructor initializer list. – J T Jul 19 '11 at 20:41