Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How bool variable value can be equals 5?

Tags:

c++

debugging

I have a method which accepts the bool variable named alarm. I need to access to some array by the index equals to alarm:

int ind = alarm; // assume here can be only '0' or '1'

But sometimes I get Access violation reading location... because of my variable equals more than 1 - 3, 5, etc:

How can this be possible?
...

Update:
the problem happens as a result of a randomize memory. I use it to simulate different input data.
Complete verifiable example on Microsoft Visual Studio 2015.

Standard Win32 console application:

#include "stdafx.h"        
#include <stdint.h>
#include <stdlib.h>

static void randomize_memory(void* pointer, size_t size)
{
    uint8_t* byteArray = reinterpret_cast<uint8_t*>(pointer);

    for (int i = 0; i < size; i++)
    {
        byteArray[i] = rand() % 0xff;
    }
}

struct MyStruct 
{
    double  a = 0;
    float   b = 0;
    bool    flag = false;
};

int main()
{
    while(true)
    {
        MyStruct st;
        randomize_memory(&st, sizeof(st));

        bool tmp = st.flag;
        int ind = tmp;

        if (ind > 1)
            __debugbreak();
    }

    return 0;
}

The behaviour tested and occurs on compilers from Visual Studio 2010 (v100) up to Visual Studio 2015 (v140).
Looks like I just should not use this way to simulate data, but much worse is that I cannot be sure that some bool variable can be casted to 0-1.

like image 551
Vladimir Bershov Avatar asked Jan 16 '26 19:01

Vladimir Bershov


1 Answers

You probably have undefined behavior somewhere in the code that is calling setAlarmSwitch.

In C++, an integer value when converted to bool takes the value false/true, which when promoted back to an integer type, become 0/1. But that doesn't mean that bool is actually stored or passed in function calls as a single bit. In fact, most ABIs have a minimal width per argument (usually the width of a general-purpose register), and any shorter integral types are promoted to it.

To illustrate the issue:

#include <iostream>

void printBool(bool x) {
    std::cout << x << std::endl;
}

int main() {
    int i = 5;
    printBool(i);
    ((void(*)(int))printBool)(i); // UB
}

Will print:

1
5

The assumption the compiler makes is that a bool argument can only contain the values 0/1 because if you follow the rules there would never be any other value passed in. It's only possible to pass another value by breaking the rules. So then:

Using a bool value in ways described by this International Standard as “undefined,” such as by examining the value of an uninitialized automatic object, might cause it to behave as if it is neither true nor false.


Your example with reinterpret_cast on the other hand is another issue, I believe a bug in MSVC. It is working fine in GCC and clang.

like image 112
rustyx Avatar answered Jan 19 '26 08:01

rustyx



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!