f



Interesting CppUnit breakage.

I had a fascinating experience with CppUnit just now.  I'm building a 
little ICMP Ping class using CppUnit in a test-first mode.  The class 
can be called with either an IP address or a hostname.  First I wrote a 
test for the IP address code:

    void getIpAddressNumeric() {
        const string stringAddress ("192.168.2.65");
        in_addr_t numericAddress = inet_addr (stringAddress.c_str());
        Pinger p (stringAddress);
        struct sockaddr_in address = p.getIpAddress();
        CPPUNIT_ASSERT (address.sin_family == AF_INET);
        CPPUNIT_ASSERT (address.sin_addr.s_addr == numericAddress);
    }

and then wrote the code to make that test pass.  Next, I wrote a test 
for hostnames:

    void getIpAddressName() {
        const string name ("bonkers");
        in_addr_t numericAddress = inet_addr ("192.168.2.65");
        Pinger p (name);
        struct sockaddr_in address = p.getIpAddress();
        CPPUNIT_ASSERT (address.sin_family == AF_INET);
        CPPUNIT_ASSERT (address.sin_addr.s_addr == numericAddress);
    }

and ran it, expecting it to fail.  It *had* to fail, since I hadn't 
written the hostname processing code yet, right?.  Amazingly enough, it 
didn't.

To make a long story short, what's going on is the two test cases each 
instantiate a Pinger object on the stack, and they both ended up at 
exactly the same place in memory (confirmed by printing &p).  The second

test case resulted in a short-circuit return in the (not yet completely 
written) constructor, but I ended up with an accidentally initialized 
object left over from the previous instantiation.  A strategic call to 
bzero() in the constructor does indeed cause the second test case to 
fail.

I guess the moral here is that you shouldn't assume your code is correct

just because the test cases work.  Forget correct, don't even assume 
that it exists :-)

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Roy
6/29/2003 10:23:20 PM
comp.lang.c++.moderated 10738 articles. 1 followers. allnor (8509) is leader. Post Follow

2 Replies
390 Views

Similar Articles

[PageSpeed] 4

Do many compilers have an option to zero out unallocated memory before
it is used for constructing objects?  That would have caught your bug.

If you're worried that zeroing out memory would tend to conceal more
bugs than it reveals, maybe the compiler could fill the memory with
random bytes before letting the constructor do its work.

-- 
Ed Avis <ed@membled.com>


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Ed
6/30/2003 6:31:16 PM
I stumbled across a similar problem once.

The object on the stack had a pointer to an optional component.
Unfortunately the respective constructor did _not_ initialise the
pointer to zero _and_ the destructor did not set it to zero after
deleting it, so when a second incarnation of the object lived at the
same address, its call to delete rose a segmentation fault. (I did not
write that code of course ;-)

The morale, I think would be to always initialise all members
correctly in the constructor, actually not very groundbreaking news.

You could have an additional test case for that, too ;-).

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
marc
7/1/2003 7:33:48 PM
Reply: