-3

I'm new to both C++ and StackOverflow and am doing an assignment on creating a Finite State Machine Sequence Detector and I am stuck at a few places. The aim of the program is to accept a binary sequence and a stream of bits with a length greater than this sequence from the user, and search for the sequence in this bit stream using different states for each bit found. I've tried searching for answers on other questions about Run-Time Check Failure #0 but am unable find anything specific to my issue. I still do not understand why these errors are occurring. The specific errors I am facing are in the debugger are

  1. Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.This takes me to a file called xstring and points to the line Xout_of_range("invalid string position");
  2. Unhandled exception: std::out_of_range at line 77: if (b.at(i) == s.at(j)) {
  3. Warning: unreferenced local variable bLength in the second try-catch block.

I know I shouldn't post the entire code but I can't think of ways to shorten it without accidentally leaving out relevant parts.

//C++ program to implement a FSM sequence detector with overlap
#include <iostream>
#include <string>
        
using namespace std;
        
struct statePair { //Defining a state pair structure with state binary string and 
                   //output value                                                                                  
    string state;
    int output=0;
};
        
int main() {
    int sequence, bitStream, count = 0, sLength = 0, bLength = 0,
    i = 0 ,j = 0, *indexes, stateNumber = 0; 
    string s, b, startState, endState, currentState;
    statePair *stateList; //Verify
    while (true) {           /*Taking input of sequence to be detected and 
                             checking if it is valid*/
        cout << "Enter a binary sequence to detect: ";
        cin >> sequence;
        auto s = to_string(sequence); 
        sLength = s.length();
        try {
            if (sLength == 0) {
                throw sequence;
            }
            for (int i = 0; i < sLength; i++) {
                if ((s.at(i) != '0') && (s.at(i) != '1')) { 
                    throw s;
                }
            }
        }
        catch (string s) {
            cout << "Error - enter a binary sequence " << endl;
        }
        catch (int sequence){
            cout << "Error - enter a binary sequence " << endl;
        }
        catch (...) {
            cout << "Error - enter a valid binary sequence"<<endl;
        }
        break;
    }
    stateList = new statePair[sLength+1];  //Verify
    endState = s;
    stateList[sLength].state = endState;
    stateList[sLength].output = 1;
    for (int i = 0; i < sLength; i++) {
        stateList[i].state = s.substr(0, stateNumber);
        stateList[i].output = 0;
    }
    while (true) {       /*Taking input of bitstream in which the sequence 
                          must be detected and checking if it is valid*/
        cout << "Enter a stream of bits: ";
        cin >> bitStream;
        auto b = to_string(bitStream);
        bLength = b.length();
        try {
            for (int i = 0; i < bLength; i++) {
                if ((b.at(i) != '0') && (b.at(i) != '1')) {
                    throw b;
                }
            }
            if (sLength > bLength) {
                throw bLength;    
            }
        }
        catch (string b) {
            cout << "Error - enter a binary sequence " << endl;
        }
        catch (int bLength) { //unreferenced local variable bLength
            cout << "Error - length of bitstream must be greater than sequence being searched" << endl;
        }
        catch (...) {
            cout << "Error - enter a valid binary sequence" << endl;
        break;
        }
    }
    indexes = new int[bLength];
    currentState = startState;
    for (int i = 0; i < bLength; i++) {   //Traversing entire bitstream
        if (b.at(i) == s.at(j)) {     //Bookmarking index of first bit match 
            currentState = stateList[j + 1].state;
            for (int j = 0; j < sLength; j++) {  //Checking for sequence at startIndex
                if (i + j < bLength) {    //Checking if enough bits are left for sequence to be found
                    if (b.substr(i, j) == currentState) {
                        currentState = stateList[j + 1].state;
                        if (currentState == endState) {
                            indexes[count] = i;
                            count++;
                            j = 0;
                            i++;
                        }
                        else {
                            currentState = startState;
                            continue;
                        }
                    }
                    else {
                        j = 0;
                        i++;
                    }
                }
                else {
                    break;
                }
            }
        }
    }
    cout << "The sequence was detected " << count << " times in the given bit stream at the indexes" << indexes << "." << endl;
    cin.get(); //To hold the console window to view output
}
  • 1
    Did you try stepping through your code with a debugger? – Algirdas Preidžius Jan 08 '21 at 12:01
  • And when you used your debugger to run this code, what did you see? This is exactly what a debugger is for. If you don't know how to use it, this is a good opportunity to learn run your program one line at a time in a debugger, monitor all variables and their values as they change, and analyse your program's logic and execution. Knowing how to use a debugger is a required skill for every C++ developer, no exceptions. We don't debug other people's code on Stackoverflow, but with your debugger's help you can find all problems in this and all future programs you write, without needing any help. – Sam Varshavchik Jan 08 '21 at 12:02
  • One useful way to simplify your code would be to remove the user input and verification code and replace it with a hard coded input that reproduces the errors you are seeing. – john Jan 08 '21 at 12:04
  • Thanks for your replies. Yes, I have tried running my code through a debugger and encountered the errors I mentioned in my question. I will now try to simplify the code as per John's comment. – Ritvik Rai Jan 08 '21 at 12:30
  • 2
    @RitvikRai "_Yes, I have tried running my code through a debugger and encountered the errors I mentioned in my question._" Just plainly "running code through debugger" won't accomplish much. It is not a magical tool, by running your code through which, it tells exactly what is wrong. Did you step through your program line by line? Investigated value of every variable at each execution step, while comparing those values with your expectations, while taking note where the execution diverges from your expectations? – Algirdas Preidžius Jan 08 '21 at 12:43

1 Answers1

0

As it was pointed out in the comments, you should LEARN how to use a debugger or how to debug a program without it (e.g. via std::cout). You are right in that you're new to C++: your code is a disaster. But since each of us once was at the same position as you're now, I'll give you some hints.

  • Error #1: The value of ESP was not properly saved across a function call. ESP is a register on the CPU that stores the stack pointer. See::What are the ESP and the EBP registers? and What and where are the stack and heap? So, most likely your program smashes the stack. Do you see the title of this portal, stack-overflow? This is pretty close to what you've managed to achieve. When one is likely to smash his stack? Most often this happens when one applies crazy/random/rubbish indexes to his arrays. Rubbish in, smashed stack out.
  • Error #2: Unhandled exception: std::out_of_range at line 77: if (b.at(i) == s.at(j)) Now I must praise you for using .at instead of the usual operator[], as at member function verifies its argument before it performs its operation. If the argument is invalid (out of range), this function throws an exception. In this way even without a debugger you know what kind of error and in which line is in your code. Here, either i is out of tange for b or j is out of range for s.
  • Warning #3 unreferenced local variable bLength in the second try-catch block. This is irrelevant here. It simply says that you declare a variable (as a catch argument) but never use it.

What else can be said about your program?

  • Your main starts from definition of 15 variables which will be used much later. This is C-language style. In C++ you should define a variable / an object as late as possible, that is, in the place you really need it. This will save you from many errors.
  • You define s as an empty string. But then use it as if it contained useful data (endState = s, b.at(i) == s.at(j)). This is the reason for error #2: you applied .at to an empty string.
  • You define some pointers only to treat them with operator new, that is, to treat them like dynamically allocated arrays. Do not do it unless you're an expert. Use std::vector, e.g. std::vector<statePair> stateList (sLength+1);
  • Your while loops will always be executed once, since the're are ended with an unconditional break. I understand what you tried to achieve, but you failed. Think it over and correct or remove the while loops altogether. Don't use code you don't understand.
  • You need not such input check as in the while loops before your code runs OK on your data.

I cannot give more hints now, since your code has too many issues to deal with. It's an avalanche. Correct those I've just pointed out and then try to fix the remaining ones. I'm sure there will be many.

zkoza
  • 2,644
  • 3
  • 16
  • 24