I have a function that iterates through a const char *
and uses the character to add objects to an instance of std::map
if it is one of series of recognized characters.
#define CHARSEQ const char*
void compile(CHARSEQ s) throw (BFCompilationError)
{
std::cout << "@Receive call " << s << std::endl;
for(int i = 0; s[i] != '\0'; i++)
{
if (std::string("<>-+.,[]").find_first_of(s[i]) == std::string::npos)
{
throw BFCompilationError("Unknown operator",*s,i);
}
std::cout << "@Compiling: " << s[i] << std::endl;
std::cout << "@address s " << (void*)s << std::endl;
std::cout << "@var s " << s << std::endl;
controlstack.top().push_back(opmap[s[i]]);
}
}
The character sequence passed is "++++++++++."
For the first three iterations, the print statements display the expected values of '+', '+', and '+', and the value of s
continues to be "+++++++++++.". However, on the fourth iteration, s
becomes mangled, producing bizarre values such as 'Ð'
, 'öê'
, 'cR '
, 'œk'
and many other character sequences. If the line that throws the exception is removed and the loop is allowed to continue, the value of s
does not change after again.
Other functions have access to s
but since this is not a multithreaded program I don't see why that would matter. I am not so much confused about why s
is changing but why it only changes on the fourth iteration.
I have searched SO and the only post that seems at all relevant is this one but it still doesn't answer my question. (Research has been difficult because searching "const char* changing value" or similar terms just comes up with hundreds of posts about what part of is is const).
Lastly, I know I should probably be using std::string
, which I will if no answers come forth, but I would still like to understand this behavior.
EDIT:
Here is the code that calls this function.
CHARSEQ text = load(s);
std::cout << "@Receive load " << text << std::endl;
try
{
compile(text);
}
catch(BFCompilationError& err)
{
std::cerr << "\nError in bf code: caught BFCompilationError @" << err.getIndex() << " in file " << s << ":\n";
std::cerr << text << '\n';
for(int i = 0; i < err.getIndex(); i++)
{
std::cerr << " ";
}
std::cerr << "^\n";
std::cerr << err.what() << err.getProblemChar() << std::endl;
return 1;
}
Where load
is:
CHARSEQ load(CHARSEQ fname)
{
std::ifstream infile (fname);
std::string data(""), line;
if (infile.is_open())
{
while(infile.good())
{
std::getline(infile,line);
std::cout << "@loading: "<< line << '\n';
data += line;
}
infile.close();
}
else
{
std::cerr << "Error: unable to open file: " << fname << std::endl;
}
return std::trim(data).c_str();
}
and the file fname
is ++++++++++.
spread such that there is one character per line.
EDIT 2:
Here is an example of console output:
@loading: +
@loading: +
@loading: +
@loading: +
@loading: +
@loading: +
@loading: +
@loading: +
@loading: +
@loading: +
@loading: .
@Receive load ++++++++++.
@Receive call ++++++++++.
@Compiling: +
@address s 0x7513e4
@var s ++++++++++.
@Compiling: +
@address s 0x7513e4
@var s ++++++++++.
@Compiling: +
@address s 0x7513e4
@var s ++++++++++.
@Compiling:
@address s 0x7513e4
@var s ßu
Error in bf code: caught BFCompilationError @4 in file bf_src/Hello.txt:
ßu
^
Unknown operatorß