c++arduino-ide

Breakpoint Instruction Executed


I was working on a Binary Class that uses Three-State Booleans to create measurable (size-wise) arrays of boolean strings that could be translated into morse code (TRUE = dash, FALSE = dot). I am using Arduino IDE (meaning I can't use anything for the std namespace) and a circuit with LEDs to test the morse code, but I will occasionally use Visual Studio 2022 to help debug issues. The problems started to come when I declared a Binary Object variable, then assigned at a constructor, and then used an overloaded assignment operator. The details Microsoft Visual Studio gave me are:

"A breakpoint instruction (__debugbreak() statement or a similar call) was executed in ConsoleApplication1.exe."

I copied the error details into my search bar and read other forum posts about this (including one of from here, Stack Overflow). What I found the issue to be was delete[] triboolList in the Assignment Operator Overload function.

void Binary::operator=(tribool newElement) { //For reference, triboolList is of tribool Type
    //The tribool type is defined as: enum tribool{DELIM=-1, FALSE, TRUE};
    delete[] triboolList; //This is the problematic line
    if (newElement == DELIM) {
        triboolList = new tribool(DELIM);
    }
    else {
        triboolList = new tribool[2];
        triboolList[0] = newElement;
        triboolList[1] = DELIM;
    }
}

When I commented out the problematic line, the code began working again. Here is my main function in case anyone was curious:

Binary code;

tribool test[5] = { FALSE,TRUE,FALSE,FALSE,DELIM };
code = Binary(test); //Parameter Construction
std::cout << code << std::endl;
//morse(code); //Functions used in the Arduino IDE that I couldn't port over to Visual Studio
//morse(code);
code = TRUE; //This line causes the Breakpoint Instruction Executed error
code += TRUE; 
code += TRUE;
//morse(code, 1); //Arduino IDE custom function that can't be tested on Visual Studio
std::cout << code << std::endl;

I know that getting rid of the problematic line fixes my issues, but I am afraid it is also wasting memory addresses. Are my concerns anything major, or am I just overreacting? (In case anyone was curious, my class does have a destructor that is just delete[] triboolList;)

Upon hearing about the rule of 3s, I will also be sharing my Copy Constructor and Copy Assignment Operator:

Binary::Binary(const Binary& copyBinary) { //Copy Constructor
    triboolList = new tribool[triLength(copyBinary.triboolList) + 1]; 
    for (int i = 0; i < (int) triLength(copyBinary.triboolList); i++) { 
        triboolList[i] = (const tribool)copyBinary.triboolList[i]; 
    } 
    triboolList[triLength(copyBinary.triboolList)] = DELIM; 
}

Binary& Binary::operator=(const Binary& copyBinary) { //Copy Assignment Operator
    delete[] triboolList;
    triboolList = copyBinary.triboolList;
    return *this;
}

Solution

  • Your assignment operator does not check for self-assignment, plus will have a double-free error since you are simply copying the pointer value between objects.

    Instead of this, the copy/swap idiom can be used.

    Since you state that Arduino does not have std::swap, it should be easily implemented using the following:

    Binary& Binary::operator=(Binary copyBinary) 
    { 
       tribool* temp = triboolList;
       triboolList = copyBinary.triboolList;
       copyBinary.triboolList = temp;
       return *this;
    }
    

    This should be equivalent to the following, if std::swap existed:

    #include <algorithm>
    //...
    Binary& Binary::operator=(Binary copyBinary) 
    { 
       std::swap(triboolList, copyBinary.triboolList);
       return *this;
    }
    

    If there are member variables other than triboolList, they also have to be swapped with the passed-in members. I am assuming that triboolList is the only member variable.