Hello, i was solving this -> kata on CodeWars.
I am using a VusialStudio 2019 to write code. When i start this project in VS no erros is presented to me. The program even works correctly for the first test case. But when i am testing it on problem's page it gives me an error:
- UndefinedBehaviorSanitizer:DEADLYSIGNAL
==1==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000429d24 bp 0x7ffc2f3f72b0 sp 0x7ffc2f3f7150 T1)
==1==The signal is caused by a READ memory access.
==1==Hint: address points to the zero page.
==1==WARNING: invalid path to external symbolizer!
==1==WARNING: Failed to use and restart external symbolizer!
#0 0x429d23 (/workspace/test+0x429d23)
#1 0x42ab1d (/workspace/test+0x42ab1d)
#2 0x429fa3 (/workspace/test+0x429fa3)
#3 0x42e2f2 (/workspace/test+0x42e2f2)
#4 0x42c9ce (/workspace/test+0x42c9ce)
#5 0x42c529 (/workspace/test+0x42c529)
#6 0x42c11b (/workspace/test+0x42c11b)
#7 0x431425 (/workspace/test+0x431425)
#8 0x42a08d (/workspace/test+0x42a08d)
#9 0x7f1b94116bf6 (/lib/x86_64-linux-gnu/libc.so.6+0x21bf6)
#10 0x4053e9 (/workspace/test+0x4053e9)
UndefinedBehaviorSanitizer can not provide additional info. ==1==ABORTING
For a while i was turning on and off parts of program to determen where the problem is. I nereved it down to this line
Program::Status_enum Program::ExecuteComand(Comand_Class* ComandToExe)
{
else if (ComandToExe->name == "div")
{
this->Registers[ComandToExe->args[0]] /= GetValue(ComandToExe->args[1]); // error here
}
}
Leter i found out that error was showing up even if i chage line to
this->Registers.begin()->second = 3; // same error
this->Registers["a"] = 2; // same error
It looks to me that any change of value causes it to throw an error. But reaading for example was ok
int a = Registers["a"];
std::cout << a; // will print a right value
So this basikly all i was able to find out by my self. Here is structer of my code.
Basikly my goal is to write a Asmbler intorpritator
// All Comands saved as this class
class Comand_Class
{
public:
std::string name; // for example mov, div, etc.
std::vector<std::string> args; // data for the comand
Comand_Class(std::string Name, std::string arg1 = "", std::string arg2 = "")
{
//..
}
Comand_Class(std::string Name, std::vector<std::string> Args)
{
//..
}
};
// I use this class to store functions cod as a small program itself
class Function_Class
{
public:
std::vector<Comand_Class*> FunctionProgram;
};
// the main class
class Program
{
std::string MSG = "-1"; // for outout
std::unordered_map <std::string, int> Registers; // map in which the problem exsist
std::vector<Comand_Class*> ProgramLines; // Starting code
std::map<std::string,Function_Class*> CallList; // Name of Function and Her code to exe
// .exe is giving me back the status, after executing a Comand_Class line, this how i know what to do next.
enum Status_enum
{
END = 0,
CALL = 1,
JUMP = 2,
RET = 3,
CONTINUE = 10,
ERROR = -1,
};
public:
std::string Start()
{
exe(this -> ProgramLines );
return MSG;
}
int GetValue(std::string arg)
{
if ('a' <= arg[0] && arg[0] <= 'z')
{
//register
return this->Registers[arg];
}
else
{
int a = std::stoi(arg);
return a;
}
}
// not related to the problem,
void preprocesing(std::string program);
Status_enum ExecuteComand(Comand_Class* ComandToExe);
void exe(std::vector<Comand_Class*> ProgramLinesToExe);
~Program()
{
for (unsigned long i = 0; i < ProgramLines.size(); i++)
{
Comand_Class* del = ProgramLines.at(i);
delete del;
}
for (auto it = CallList.begin(); it != CallList.end(); it++)
{
for (unsigned long i = 0; i < it->second->FunctionProgram.size(); i++)
{
Comand_Class* del = it->second->FunctionProgram.at(i);
delete del;
}
}
// add CallList to clear
}
};
// this function is recurseve, Can this be a reson why it brakes?
void Program::exe(std::vector<Comand_Class*> ProgramLinesToExe)
{
Status_enum Status;
unsigned long int SubPC = 0; // Comand to exe
while (SubPC < ProgramLinesToExe.size())
{
Status = ExecuteComand(ProgramLinesToExe[SubPC]);
if (Status != CONTINUE)
{
if(Status == JUMP)
{
exe(CallList[ProgramLinesToExe[SubPC]->args[0]]->FunctionProgram);
}
else if (Status == CALL)
{
auto test = CallList[ProgramLinesToExe[SubPC]->args[0]]->FunctionProgram;
exe(CallList[ProgramLinesToExe[SubPC]->args[0]]->FunctionProgram);
}
else if (Status == RET)
{
return;
}
else if (Status == END)
{
break;
}
else if (Status == ERROR)
{
std::cout << "Unknown comand! " << ProgramLinesToExe[SubPC]->name;
}
}
SubPC++;
}
}
// Untill this function called second time (recursively) all works good
Program::Status_enum Program::ExecuteComand(Comand_Class* ComandToExe)
{
if (ComandToExe->name == "mov")
{
this->Registers[ComandToExe->args[0]] = GetValue(ComandToExe->args[1]);
}
else if (ComandToExe->name == "inc")
{
this->Registers[ComandToExe->args[0]]++;
}
else if (ComandToExe->name == "dec")
{
this->Registers[ComandToExe->args[0]]--;
}
else if (ComandToExe->name == "add")
{
this->Registers[ComandToExe->args[0]] += GetValue(ComandToExe->args[1]);
}
else if (ComandToExe->name == "sub")
{
this->Registers[ComandToExe->args[0]] -= GetValue(ComandToExe->args[1]);
}
else if (ComandToExe->name == "mil")
{
this->Registers[ComandToExe->args[0]] *= GetValue(ComandToExe->args[1]);
}
else if (ComandToExe->name == "div")
{
//this->Registers[ComandToExe->args[0]] /= GetValue(ComandToExe->args[1]); error
}
else if (ComandToExe->name == "cmp")
{
int x = GetValue(ComandToExe->args[0]);
int y = GetValue(ComandToExe->args[1]);
this->CompareFlugs.Equal = (x == y);
this->CompareFlugs.Less = (x < y);
}
else if (ComandToExe->name == "jne") // if the values of the previous cmp command were not equal.
{
if (this->CompareFlugs.Equal == false)
{
return JUMP;
}
}
else if (ComandToExe->name == "je") // if the values of the previous cmp command were equal.
{
if (this->CompareFlugs.Equal == true)
{
return JUMP;
}
}
else if (ComandToExe->name == "jge") // if x was greater or equal than y in the previous cmp command.
{
if (this->CompareFlugs.Less == false)
{
return JUMP;
}
}
else if (ComandToExe->name == "jg") // f x was greater than y in the previous cmp command.
{
if ((this->CompareFlugs.Less == false) && (this->CompareFlugs.Equal == false))
{
return JUMP;
}
}
else if (ComandToExe->name == "jle") // if x was less or equal than y in the previous cmp command.
{
if ((this->CompareFlugs.Less == true) || (this->CompareFlugs.Equal == true))
{
return JUMP;
}
}
else if (ComandToExe->name == "jl") // if x was less than y in the previous cmp command.
{
if (this->CompareFlugs.Less == true)
{
return JUMP;
}
}
else if (ComandToExe->name == "call")
{
return CALL;
}
else if (ComandToExe->name == "ret")
{
return RET;
}
else if (ComandToExe->name == "end")
{
return END;
}
else if (ComandToExe->name == "msg")
{
MSG = "";
for (unsigned long int i = 0; i < ComandToExe->args.size(); i++)
{
if (ComandToExe->args[i][0] == '\'')
{
MSG += ComandToExe->args[i].substr(1);
}
else
{
MSG += std::to_string(GetValue(ComandToExe->args[i]));
}
}
}
else
{
return ERROR;
}
return CONTINUE;
}
That's all. Also i am new to stackoverflow, so if i did somting very bad, do not judge strictly. And Here all the code, becase i cut parts i think was usless:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <map>
#include <unordered_map>
#include <regex>
class Comand_Class
{
public:
std::string name;
std::vector<std::string> args;
Comand_Class(std::string Name, std::string arg1 = "", std::string arg2 = "")
{
name = Name;
args.push_back(arg1);
if (!arg2.empty())
{
args.push_back(arg2);
}
}
Comand_Class(std::string Name, std::vector<std::string> Args)
{
name = Name;
args = Args;
}
};
class Function_Class
{
public:
//Comand_Class* ReturnControlTo = NULL;
std::vector<Comand_Class*> FunctionProgram;
};
class Program
{
//int PC = 0;
std::string MSG = "-1";
std::unordered_map <std::string, int> Registers;
std::vector<Comand_Class*> ProgramLines;
std::map<std::string,Function_Class*> CallList;
class CompareFlugs_Class
{
public:
bool Less = false;
bool Equal = false;
}CompareFlugs;
enum Status_enum
{
END = 0,
CALL = 1,
JUMP = 2,
RET = 3,
CONTINUE = 10,
ERROR = -1,
};
const std::string AllowedCommands = "mov inc dev add sub mul div cmp";
public:
std::string Start()
{
exe(this -> ProgramLines );
return MSG;
}
int GetValue(std::string arg)
{
if ('a' <= arg[0] && arg[0] <= 'z')
{
//register
return this->Registers[arg];
}
else
{
int a = std::stoi(arg);
return a;
}
}
void preprocesing(std::string program);
Status_enum ExecuteComand(Comand_Class* ComandToExe);
void exe(std::vector<Comand_Class*> ProgramLinesToExe);
~Program()
{
for (unsigned long i = 0; i < ProgramLines.size(); i++)
{
Comand_Class* del = ProgramLines.at(i);
delete del;
}
for (auto it = CallList.begin(); it != CallList.end(); it++)
{
for (unsigned long i = 0; i < it->second->FunctionProgram.size(); i++)
{
Comand_Class* del = it->second->FunctionProgram.at(i);
delete del;
}
}
// add CallList to clear
}
};
void Program::preprocesing(std::string program)
{
std::string read;
Comand_Class*NewProgramLine;
std::istringstream iss(program);
std::smatch matches;
std::regex Comand(";(.*)|call\\s(.*)|(end|ret)|msg(.*)[;]?|(\\w+):|(j\\w{1,2})\\s+(\\w+)|(\\w+)\\s+(\\w),?\\s?(\\d+|\\w)?");
bool WtireToFunction = false;
std::string ActiveLabel;
Function_Class* NewFunction = nullptr;// = new Function_Class;
while (!iss.eof())
{
std::getline(iss, read);
std::regex_search(read, matches, Comand);
/*
if (matches.size() != 0)
std::cout << "Comand is " << matches[0] << "\n";
*/
// parcing
std::string Coment = matches[1];
std::string CallLabel = matches[2];
std::string End = matches[3];
std::string Message = matches[4]; // may contain a comment in the end
std::string Label = matches[5];
std::string JumpComand = matches[6];
std::string JumpLabel = matches[7];
std::string ComandName = matches[8];
std::string arg1 = matches[9];
std::string arg2 = matches[10];
if ((!ComandName.empty()) && (AllowedCommands.find(ComandName) != std::string::npos))
{
//std::cout << "Comand is " << matches[0] << "\n";
std::cout << "Comand is " << ComandName << " " << arg1 << " " << arg2 << "\n";
NewProgramLine = new Comand_Class (ComandName,arg1,arg2);
//NewProgramLine->name = ComandName;
//NewProgramLine->args.push_back(arg1);
if (WtireToFunction == false)
{
this->ProgramLines.push_back(NewProgramLine);
}
else
{
NewFunction->FunctionProgram.push_back(NewProgramLine);
}
}
else if (!JumpComand.empty()) // && (AllowedJumpComands.find(JumpComand) != std::string::npos))
{
std::cout << "Comand is " << JumpComand << " " << JumpLabel << "\n";
NewProgramLine = new Comand_Class(JumpComand, JumpLabel);
}
else if (!CallLabel.empty()) // on call
{
NewProgramLine = new Comand_Class("call", CallLabel);
this->ProgramLines.push_back(NewProgramLine); // add Call to the ProgramLines
}
else if (!Label.empty()) // Generate New SubProgram
{
WtireToFunction = true;
ActiveLabel = Label;
NewFunction = new Function_Class;
this->CallList[ActiveLabel] = NewFunction;
}
else if (!Message.empty())
{
std::regex MessageParcing("('.*)'|,\\s(\\w)");
std::smatch matches;
std::sregex_iterator it(Message.begin(), Message.end(), MessageParcing), end;
std::vector<std::string> args;
while (it!= end)
{
matches = *it;
if (!matches[1].str().empty())
{
args.push_back(matches[1].str());
}
else if (!matches[2].str().empty())
{
args.push_back(matches[2].str());
}
else
{
std::cout << "Error: cannot format msg\n";
}
it++;
}
NewProgramLine = new Comand_Class("msg",args);
this->ProgramLines.push_back(NewProgramLine);
}
else if (!End.empty())
{
if (End == "end")
{
NewProgramLine = new Comand_Class("end");
this->ProgramLines.push_back(NewProgramLine); // add Call to the ProgramLines
}
if (End == "ret")
{
if (NewFunction == nullptr)
std::cout << "No Call Detected, but ret is found\n";
else
{
NewProgramLine = new Comand_Class("ret");
NewFunction->FunctionProgram.push_back(NewProgramLine);
}
}
}
}
}
Program::Status_enum Program::ExecuteComand(Comand_Class* ComandToExe)
{
if (ComandToExe->name == "mov")
{
this->Registers[ComandToExe->args[0]] = GetValue(ComandToExe->args[1]);
}
else if (ComandToExe->name == "inc")
{
this->Registers[ComandToExe->args[0]]++;
}
else if (ComandToExe->name == "dec")
{
this->Registers[ComandToExe->args[0]]--;
}
else if (ComandToExe->name == "add")
{
this->Registers[ComandToExe->args[0]] += GetValue(ComandToExe->args[1]);
}
else if (ComandToExe->name == "sub")
{
this->Registers[ComandToExe->args[0]] -= GetValue(ComandToExe->args[1]);
}
else if (ComandToExe->name == "mil")
{
this->Registers[ComandToExe->args[0]] *= GetValue(ComandToExe->args[1]);
}
else if (ComandToExe->name == "div")
{
int a = GetValue(ComandToExe->args[1]);
auto t = ComandToExe->args[0];
int b = 6 / 2;
this->MSG = "Hi";
this->Registers[t] = b;
this->Registers.begin()->second = 3;
//this->Registers[ComandToExe->args[0]] /= GetValue(ComandToExe->args[1]);
}
else if (ComandToExe->name == "cmp")
{
int x = GetValue(ComandToExe->args[0]);
int y = GetValue(ComandToExe->args[1]);
this->CompareFlugs.Equal = (x == y);
this->CompareFlugs.Less = (x < y);
}
else if (ComandToExe->name == "jne") // if the values of the previous cmp command were not equal.
{
if (this->CompareFlugs.Equal == false)
{
return JUMP;
}
}
else if (ComandToExe->name == "je") // if the values of the previous cmp command were equal.
{
if (this->CompareFlugs.Equal == true)
{
return JUMP;
}
}
else if (ComandToExe->name == "jge") // if x was greater or equal than y in the previous cmp command.
{
if (this->CompareFlugs.Less == false)
{
return JUMP;
}
}
else if (ComandToExe->name == "jg") // f x was greater than y in the previous cmp command.
{
if ((this->CompareFlugs.Less == false) && (this->CompareFlugs.Equal == false))
{
return JUMP;
}
}
else if (ComandToExe->name == "jle") // if x was less or equal than y in the previous cmp command.
{
if ((this->CompareFlugs.Less == true) || (this->CompareFlugs.Equal == true))
{
return JUMP;
}
}
else if (ComandToExe->name == "jl") // if x was less than y in the previous cmp command.
{
if (this->CompareFlugs.Less == true)
{
return JUMP;
}
}
else if (ComandToExe->name == "call")
{
// написать адресс для возврата в структуру с функциями
return CALL;
}
else if (ComandToExe->name == "ret")
{
return RET;
}
else if (ComandToExe->name == "end")
{
return END;
}
else if (ComandToExe->name == "msg")
{
MSG = "";
for (unsigned long int i = 0; i < ComandToExe->args.size(); i++)
{
if (ComandToExe->args[i][0] == '\'')
{
MSG += ComandToExe->args[i].substr(1);
}
else
{
MSG += std::to_string(GetValue(ComandToExe->args[i]));
}
}
}
else
{
return ERROR;
}
return CONTINUE;
}
void Program::exe(std::vector<Comand_Class*> ProgramLinesToExe)
{
Status_enum Status;
unsigned long int SubPC = 0;
while (SubPC < ProgramLinesToExe.size())
{
Status = ExecuteComand(ProgramLinesToExe[SubPC]);
if (Status != CONTINUE)
{
if(Status == JUMP)
{
exe(CallList[ProgramLinesToExe[SubPC]->args[0]]->FunctionProgram);
}
else if (Status == CALL)
{
auto test = CallList[ProgramLinesToExe[SubPC]->args[0]]->FunctionProgram;
exe(CallList[ProgramLinesToExe[SubPC]->args[0]]->FunctionProgram);
}
else if (Status == RET)
{
return;
}
else if (Status == END)
{
break;
}
else if (Status == ERROR)
{
std::cout << "Unknown comand! " << ProgramLinesToExe[SubPC]->name;
}
}
SubPC++;
}
}
std::string assembler_interpreter(std::string program)
{
Program Main;
Main.preprocesing(program);
return Main.Start();
}