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 :oops:

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