Page 1 of 1
Wow, both (x) and (!x) are false !!!
Posted: Sun Aug 30, 2009 5:20 am
by torshie
I have implemented a simple unit test framework in my kernel. The framework was fine until I wrote these three lines of code:
Code: Select all
bool x = tree->root->payload.black;
UNIT_ASSERT(x);
UNIT_ASSERT(!x);
Both of the two assertions failed !!!
UNIT_ASSERT is a macro:
Code: Select all
#define UNIT_ASSERT(a) Assert::assert((a), __LINE__, __FILE__, #a)
Assert::assert is a static method
Code: Select all
void Assert::assert(bool v, int line, char const* file,
char const* string) {
if (!v) {
++failed;
Utils::console << "Assertion failed, " << file << ":" << line
<< ": " << string << "\n";
TestManager& manager = getSingleInstance<TestManager>();
if (manager.stopOnFailure()) {
System::stop();
}
} else {
++passed;
}
}
Attached is a screenshot
What are possible reasons of this strange behavior?
Cheers
torshie
EDIT: JamesM: Changed topic name.
Re: God, both (x) and (!x) are false !!!
Posted: Sun Aug 30, 2009 7:18 am
by DeleteMe
I have made that mistake, too. for me it goes like this, say x = 23 then bool(x) = true and bool(!x) = true. i sounds nasty, right?
Re: God, both (x) and (!x) are false !!!
Posted: Sun Aug 30, 2009 8:09 am
by torshie
pcfreck wrote:I have made that mistake, too. for me it goes like this, say x = 23 then bool(x) = true and bool(!x) = true. i sounds nasty, right?
How did you solve the problem?
Re: God, both (x) and (!x) are false !!!
Posted: Sun Aug 30, 2009 2:48 pm
by Brendan
Hi,
torshie wrote:pcfreck wrote:I have made that mistake, too. for me it goes like this, say x = 23 then bool(x) = true and bool(!x) = true. i sounds nasty, right?
How did you solve the problem?
I'd guess you'd need to use a comparison (e.g. "UNIT_ASSERT(x == 0)" and "UNIT_ASSERT(x != 0)") to convert the integer into a bool (instead of doing a bitwise NOT, which only inverts each bit).
Cheers,
Brendan
Re: Wow, both (x) and (!x) are false !!!
Posted: Sun Aug 30, 2009 2:59 pm
by NickJohnson
But ! does a boolean not instead of a bitwise not, right? ~ would invert each bit, but shouldn't ! be 0 if the input is nonzero? Otherwise, checking for null pointers with ! wouldn't work. (x == 0) <=> (!x), right?
Re: Wow, both (x) and (!x) are false !!!
Posted: Sun Aug 30, 2009 3:37 pm
by Brendan
Hi,
NickJohnson wrote:But ! does a boolean not instead of a bitwise not, right? ~ would invert each bit, but shouldn't ! be 0 if the input is nonzero? Otherwise, checking for null pointers with ! wouldn't work. (x == 0) <=> (!x), right?
Doh, you're right
I'm confused now - I can't see how both x and !x can be nonzero.
Cheers,
Brendan
Re: Wow, both (x) and (!x) are false !!!
Posted: Sun Aug 30, 2009 4:21 pm
by pcmattman
Code: Select all
bool x = tree->root->payload.black;
UNIT_ASSERT(x);
UNIT_ASSERT(!x);
What is the value of payload.black? Step back for a moment and try something like this:
Code: Select all
bool x = tree->root->payload.black;
log("black is %d\n", tree->root->payload.black);
if(x)
log("x = true");
if(!x)
log("x = false");
If that does what you want it to, then your UNIT_ASSERT function may be incorrect (in some way). If it doesn't, then you may want to start inspecting the resulting assembly to see what's being run.
Re: Wow, both (x) and (!x) are false !!!
Posted: Sun Aug 30, 2009 7:07 pm
by tantrikwizard
try:
#define assert(x) if (!(x)){ panic(#x); }
Re: God, both (x) and (!x) are false !!!
Posted: Sun Aug 30, 2009 7:12 pm
by Kitsune
pcfreck wrote:I have made that mistake, too. for me it goes like this, say x = 23 then bool(x) = true and bool(!x) = true. i sounds nasty, right?
Is that a case of using "=" instead of "==" in your comparison?
As for the OP... maybe try messing with those 3 lines a bit, i.e. comment out the assignment and try it with 'x = true', and if that operates as expected, try uncommenting the assignment and adding 'x = true' after the original one, and maybe also try the UNIT_ASSERT directly on the
tree->root->payload.black.
Re: Wow, both (x) and (!x) are false !!!
Posted: Sun Aug 30, 2009 11:04 pm
by Solar
Well, first thing I would do is, have the values of x and !x printed to screen...
Re: Wow, both (x) and (!x) are false !!!
Posted: Mon Aug 31, 2009 1:07 am
by torshie
Hi,
Thanks for all the replies.
I get the cause.
The variable x was optimized out, even -O0 was used, and the value of tree->root->payload.black was false. That means UNIT_ASSERT(x) should fail. After UNIT_ASSERT(x) failed, a counter was increased from 0 to 1. Because of a bug in my allocator, tree->root->payload.black was allocated right at the address of the counter, so when the counter was changed, the value of tree->root->payload.black was also changed from 0 to 1, so UNIT_ASSERT(!x) also failed.
I just payed too much attention to the two failed assertions and didn't notice the page fault (did you see it on the screenshot?). The page fault was cause by a deference of a null pointer which was also caused by the allocator bug. If I had noticed the page fault, it shouldn't have taken me so much time to find out the bug.
Thanks again
torshie