Brainfuck interpreter strange output












0















I've decided to write a simple Brainfuck IDE in C++ using Borland's CppBuilder6. I've put on my for a RichEdit and made it look somewhat like notepad. Then I've added TEdit for input and TMemo for output. After some tests, I thought that RichEdit is bad component to use in my case and I changed it to TMemo.



In my code input = Edit2, code = Memo2, output = Memo1. I rewrote it two times and this version seems most correct; I've decided to not use pointers (i thought about it and even wrote pointer version, unfortunately it didn't work too so for simplifying I've removed pointers).



char *cells = (char*)calloc(65536,1); //Should i use malloc?
int cellp = 0;
void __fastcall BFIde::interpret() {
char* pf = Memo2->Lines->Text.c_str(); //Weird output
char* p = (char*)malloc(strlen(pf)+1);
strcpy(p, pf); //Because pf is constant, i need to copy it into not constant string.
int pp = 0;

MessageBox(NULL,p,NULL,MB_OK); //To ensure that program is correct, but it ain't.

while(p[pp]){
switch(p[pp]){
case '>':
cellp++;
break;
case '<':
cellp--;
break;
case '+':
MessageBox(NULL, "Plus", NULL, MB_OK); //When executing test code, never gets shown.
cells[cellp]++;
break;
case '-':
cells[cellp]--;
break;
case '.':{ //It should look other, but I've replaced it to ensure that output is correct.
char arr[2]={cells[cellp],0};MessageBox(NULL, arr, NULL, MB_OK);}
break;
case ',': //Remove first character and pass it to program
if(Edit2->Text == "")cells[cellp] = 0;
else {cells[cellp] = Edit2->Text.c_str()[0];char* str;strcpy(str, Edit2->Text.c_str());Edit2->Text=str++;}
break;
case '[':{ //Propably works.
int bal = 1;
if (cells[cellp] == '') {
do {
pp++;
if (p[pp] == '[') bal++;
else if (p[pp] == ']') bal--;
} while ( bal != 0 );
}
break;
}
case ']':
int bal2 = 0;
do {
if (p[pp] == '[') bal2++;
else if (p[pp] == ']') bal2--;
pp--;
} while ( bal2 != 0 );
break;
}
pp++;
}
MessageBox(NULL, IntToStr(cellp).c_str(), NULL, MB_OK); //To check that something was parsed. Shows 0 everytime (not expected).
}


When i enter some code, eg. "+." and execute this function (via button), this shows series of messagebox. First: (line 8), second: 0 (line 55), and nothing more shows. Expected result was to write: First +., second Plus, and empty 3rd. What I've made wrong in my code? Maybe I've missed something.










share|improve this question




















  • 2





    And what have you done so far to debug this yourself? StackOverflow is not a debugging service. You have an expected result, so step through your code with the debugger until it deviates from that expectation, and then you can figure out why it deviates. But I can tell you right now, your overzealous use of Text.c_str() is very wrong, but especially the first one: char* pf = Memo2->Lines->Text.c_str(); char* p = (char*)malloc(strlen(pf)+1); strcpy(p, pf);. Why do you think that is wrong? I will give you a hint - it has UNDEFINED BEHAVIOR!

    – Remy Lebeau
    Apr 25 '17 at 0:19













  • @RemyLebeau Have you ever used c++builder6 debugger?

    – Krzysztof Szewczyk
    Apr 25 '17 at 15:08











  • All the time. BCB6 is the compiler I have to use at my day job :-( But the issue you describe is not limited to just BCB6. You have errors in your code, so it would be broken in any compiler version.

    – Remy Lebeau
    Apr 25 '17 at 15:11













  • bcb6 debugger shown me error at end of caller procedure.

    – Krzysztof Szewczyk
    Apr 25 '17 at 15:19











  • There are errors in your code, starting with the very first line of your interpret() function. Do you understand WHY that line of code is faulty? You are taking a pointer to temporary data that gets freed immediately after you take the pointer, so the subsequent lines of code are operating on invalid memory. There is another memory error in your ',' handler - you are trying to copying data to an uninitialized pointer that is not pointing at valid memory.

    – Remy Lebeau
    Apr 25 '17 at 15:33


















0















I've decided to write a simple Brainfuck IDE in C++ using Borland's CppBuilder6. I've put on my for a RichEdit and made it look somewhat like notepad. Then I've added TEdit for input and TMemo for output. After some tests, I thought that RichEdit is bad component to use in my case and I changed it to TMemo.



In my code input = Edit2, code = Memo2, output = Memo1. I rewrote it two times and this version seems most correct; I've decided to not use pointers (i thought about it and even wrote pointer version, unfortunately it didn't work too so for simplifying I've removed pointers).



char *cells = (char*)calloc(65536,1); //Should i use malloc?
int cellp = 0;
void __fastcall BFIde::interpret() {
char* pf = Memo2->Lines->Text.c_str(); //Weird output
char* p = (char*)malloc(strlen(pf)+1);
strcpy(p, pf); //Because pf is constant, i need to copy it into not constant string.
int pp = 0;

MessageBox(NULL,p,NULL,MB_OK); //To ensure that program is correct, but it ain't.

while(p[pp]){
switch(p[pp]){
case '>':
cellp++;
break;
case '<':
cellp--;
break;
case '+':
MessageBox(NULL, "Plus", NULL, MB_OK); //When executing test code, never gets shown.
cells[cellp]++;
break;
case '-':
cells[cellp]--;
break;
case '.':{ //It should look other, but I've replaced it to ensure that output is correct.
char arr[2]={cells[cellp],0};MessageBox(NULL, arr, NULL, MB_OK);}
break;
case ',': //Remove first character and pass it to program
if(Edit2->Text == "")cells[cellp] = 0;
else {cells[cellp] = Edit2->Text.c_str()[0];char* str;strcpy(str, Edit2->Text.c_str());Edit2->Text=str++;}
break;
case '[':{ //Propably works.
int bal = 1;
if (cells[cellp] == '') {
do {
pp++;
if (p[pp] == '[') bal++;
else if (p[pp] == ']') bal--;
} while ( bal != 0 );
}
break;
}
case ']':
int bal2 = 0;
do {
if (p[pp] == '[') bal2++;
else if (p[pp] == ']') bal2--;
pp--;
} while ( bal2 != 0 );
break;
}
pp++;
}
MessageBox(NULL, IntToStr(cellp).c_str(), NULL, MB_OK); //To check that something was parsed. Shows 0 everytime (not expected).
}


When i enter some code, eg. "+." and execute this function (via button), this shows series of messagebox. First: (line 8), second: 0 (line 55), and nothing more shows. Expected result was to write: First +., second Plus, and empty 3rd. What I've made wrong in my code? Maybe I've missed something.










share|improve this question




















  • 2





    And what have you done so far to debug this yourself? StackOverflow is not a debugging service. You have an expected result, so step through your code with the debugger until it deviates from that expectation, and then you can figure out why it deviates. But I can tell you right now, your overzealous use of Text.c_str() is very wrong, but especially the first one: char* pf = Memo2->Lines->Text.c_str(); char* p = (char*)malloc(strlen(pf)+1); strcpy(p, pf);. Why do you think that is wrong? I will give you a hint - it has UNDEFINED BEHAVIOR!

    – Remy Lebeau
    Apr 25 '17 at 0:19













  • @RemyLebeau Have you ever used c++builder6 debugger?

    – Krzysztof Szewczyk
    Apr 25 '17 at 15:08











  • All the time. BCB6 is the compiler I have to use at my day job :-( But the issue you describe is not limited to just BCB6. You have errors in your code, so it would be broken in any compiler version.

    – Remy Lebeau
    Apr 25 '17 at 15:11













  • bcb6 debugger shown me error at end of caller procedure.

    – Krzysztof Szewczyk
    Apr 25 '17 at 15:19











  • There are errors in your code, starting with the very first line of your interpret() function. Do you understand WHY that line of code is faulty? You are taking a pointer to temporary data that gets freed immediately after you take the pointer, so the subsequent lines of code are operating on invalid memory. There is another memory error in your ',' handler - you are trying to copying data to an uninitialized pointer that is not pointing at valid memory.

    – Remy Lebeau
    Apr 25 '17 at 15:33
















0












0








0








I've decided to write a simple Brainfuck IDE in C++ using Borland's CppBuilder6. I've put on my for a RichEdit and made it look somewhat like notepad. Then I've added TEdit for input and TMemo for output. After some tests, I thought that RichEdit is bad component to use in my case and I changed it to TMemo.



In my code input = Edit2, code = Memo2, output = Memo1. I rewrote it two times and this version seems most correct; I've decided to not use pointers (i thought about it and even wrote pointer version, unfortunately it didn't work too so for simplifying I've removed pointers).



char *cells = (char*)calloc(65536,1); //Should i use malloc?
int cellp = 0;
void __fastcall BFIde::interpret() {
char* pf = Memo2->Lines->Text.c_str(); //Weird output
char* p = (char*)malloc(strlen(pf)+1);
strcpy(p, pf); //Because pf is constant, i need to copy it into not constant string.
int pp = 0;

MessageBox(NULL,p,NULL,MB_OK); //To ensure that program is correct, but it ain't.

while(p[pp]){
switch(p[pp]){
case '>':
cellp++;
break;
case '<':
cellp--;
break;
case '+':
MessageBox(NULL, "Plus", NULL, MB_OK); //When executing test code, never gets shown.
cells[cellp]++;
break;
case '-':
cells[cellp]--;
break;
case '.':{ //It should look other, but I've replaced it to ensure that output is correct.
char arr[2]={cells[cellp],0};MessageBox(NULL, arr, NULL, MB_OK);}
break;
case ',': //Remove first character and pass it to program
if(Edit2->Text == "")cells[cellp] = 0;
else {cells[cellp] = Edit2->Text.c_str()[0];char* str;strcpy(str, Edit2->Text.c_str());Edit2->Text=str++;}
break;
case '[':{ //Propably works.
int bal = 1;
if (cells[cellp] == '') {
do {
pp++;
if (p[pp] == '[') bal++;
else if (p[pp] == ']') bal--;
} while ( bal != 0 );
}
break;
}
case ']':
int bal2 = 0;
do {
if (p[pp] == '[') bal2++;
else if (p[pp] == ']') bal2--;
pp--;
} while ( bal2 != 0 );
break;
}
pp++;
}
MessageBox(NULL, IntToStr(cellp).c_str(), NULL, MB_OK); //To check that something was parsed. Shows 0 everytime (not expected).
}


When i enter some code, eg. "+." and execute this function (via button), this shows series of messagebox. First: (line 8), second: 0 (line 55), and nothing more shows. Expected result was to write: First +., second Plus, and empty 3rd. What I've made wrong in my code? Maybe I've missed something.










share|improve this question
















I've decided to write a simple Brainfuck IDE in C++ using Borland's CppBuilder6. I've put on my for a RichEdit and made it look somewhat like notepad. Then I've added TEdit for input and TMemo for output. After some tests, I thought that RichEdit is bad component to use in my case and I changed it to TMemo.



In my code input = Edit2, code = Memo2, output = Memo1. I rewrote it two times and this version seems most correct; I've decided to not use pointers (i thought about it and even wrote pointer version, unfortunately it didn't work too so for simplifying I've removed pointers).



char *cells = (char*)calloc(65536,1); //Should i use malloc?
int cellp = 0;
void __fastcall BFIde::interpret() {
char* pf = Memo2->Lines->Text.c_str(); //Weird output
char* p = (char*)malloc(strlen(pf)+1);
strcpy(p, pf); //Because pf is constant, i need to copy it into not constant string.
int pp = 0;

MessageBox(NULL,p,NULL,MB_OK); //To ensure that program is correct, but it ain't.

while(p[pp]){
switch(p[pp]){
case '>':
cellp++;
break;
case '<':
cellp--;
break;
case '+':
MessageBox(NULL, "Plus", NULL, MB_OK); //When executing test code, never gets shown.
cells[cellp]++;
break;
case '-':
cells[cellp]--;
break;
case '.':{ //It should look other, but I've replaced it to ensure that output is correct.
char arr[2]={cells[cellp],0};MessageBox(NULL, arr, NULL, MB_OK);}
break;
case ',': //Remove first character and pass it to program
if(Edit2->Text == "")cells[cellp] = 0;
else {cells[cellp] = Edit2->Text.c_str()[0];char* str;strcpy(str, Edit2->Text.c_str());Edit2->Text=str++;}
break;
case '[':{ //Propably works.
int bal = 1;
if (cells[cellp] == '') {
do {
pp++;
if (p[pp] == '[') bal++;
else if (p[pp] == ']') bal--;
} while ( bal != 0 );
}
break;
}
case ']':
int bal2 = 0;
do {
if (p[pp] == '[') bal2++;
else if (p[pp] == ']') bal2--;
pp--;
} while ( bal2 != 0 );
break;
}
pp++;
}
MessageBox(NULL, IntToStr(cellp).c_str(), NULL, MB_OK); //To check that something was parsed. Shows 0 everytime (not expected).
}


When i enter some code, eg. "+." and execute this function (via button), this shows series of messagebox. First: (line 8), second: 0 (line 55), and nothing more shows. Expected result was to write: First +., second Plus, and empty 3rd. What I've made wrong in my code? Maybe I've missed something.







c++ interpreter vcl c++builder-6 brainfuck






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 22 '18 at 18:42









Zoe

11.4k74278




11.4k74278










asked Apr 22 '17 at 10:57









Krzysztof SzewczykKrzysztof Szewczyk

646627




646627








  • 2





    And what have you done so far to debug this yourself? StackOverflow is not a debugging service. You have an expected result, so step through your code with the debugger until it deviates from that expectation, and then you can figure out why it deviates. But I can tell you right now, your overzealous use of Text.c_str() is very wrong, but especially the first one: char* pf = Memo2->Lines->Text.c_str(); char* p = (char*)malloc(strlen(pf)+1); strcpy(p, pf);. Why do you think that is wrong? I will give you a hint - it has UNDEFINED BEHAVIOR!

    – Remy Lebeau
    Apr 25 '17 at 0:19













  • @RemyLebeau Have you ever used c++builder6 debugger?

    – Krzysztof Szewczyk
    Apr 25 '17 at 15:08











  • All the time. BCB6 is the compiler I have to use at my day job :-( But the issue you describe is not limited to just BCB6. You have errors in your code, so it would be broken in any compiler version.

    – Remy Lebeau
    Apr 25 '17 at 15:11













  • bcb6 debugger shown me error at end of caller procedure.

    – Krzysztof Szewczyk
    Apr 25 '17 at 15:19











  • There are errors in your code, starting with the very first line of your interpret() function. Do you understand WHY that line of code is faulty? You are taking a pointer to temporary data that gets freed immediately after you take the pointer, so the subsequent lines of code are operating on invalid memory. There is another memory error in your ',' handler - you are trying to copying data to an uninitialized pointer that is not pointing at valid memory.

    – Remy Lebeau
    Apr 25 '17 at 15:33
















  • 2





    And what have you done so far to debug this yourself? StackOverflow is not a debugging service. You have an expected result, so step through your code with the debugger until it deviates from that expectation, and then you can figure out why it deviates. But I can tell you right now, your overzealous use of Text.c_str() is very wrong, but especially the first one: char* pf = Memo2->Lines->Text.c_str(); char* p = (char*)malloc(strlen(pf)+1); strcpy(p, pf);. Why do you think that is wrong? I will give you a hint - it has UNDEFINED BEHAVIOR!

    – Remy Lebeau
    Apr 25 '17 at 0:19













  • @RemyLebeau Have you ever used c++builder6 debugger?

    – Krzysztof Szewczyk
    Apr 25 '17 at 15:08











  • All the time. BCB6 is the compiler I have to use at my day job :-( But the issue you describe is not limited to just BCB6. You have errors in your code, so it would be broken in any compiler version.

    – Remy Lebeau
    Apr 25 '17 at 15:11













  • bcb6 debugger shown me error at end of caller procedure.

    – Krzysztof Szewczyk
    Apr 25 '17 at 15:19











  • There are errors in your code, starting with the very first line of your interpret() function. Do you understand WHY that line of code is faulty? You are taking a pointer to temporary data that gets freed immediately after you take the pointer, so the subsequent lines of code are operating on invalid memory. There is another memory error in your ',' handler - you are trying to copying data to an uninitialized pointer that is not pointing at valid memory.

    – Remy Lebeau
    Apr 25 '17 at 15:33










2




2





And what have you done so far to debug this yourself? StackOverflow is not a debugging service. You have an expected result, so step through your code with the debugger until it deviates from that expectation, and then you can figure out why it deviates. But I can tell you right now, your overzealous use of Text.c_str() is very wrong, but especially the first one: char* pf = Memo2->Lines->Text.c_str(); char* p = (char*)malloc(strlen(pf)+1); strcpy(p, pf);. Why do you think that is wrong? I will give you a hint - it has UNDEFINED BEHAVIOR!

– Remy Lebeau
Apr 25 '17 at 0:19







And what have you done so far to debug this yourself? StackOverflow is not a debugging service. You have an expected result, so step through your code with the debugger until it deviates from that expectation, and then you can figure out why it deviates. But I can tell you right now, your overzealous use of Text.c_str() is very wrong, but especially the first one: char* pf = Memo2->Lines->Text.c_str(); char* p = (char*)malloc(strlen(pf)+1); strcpy(p, pf);. Why do you think that is wrong? I will give you a hint - it has UNDEFINED BEHAVIOR!

– Remy Lebeau
Apr 25 '17 at 0:19















@RemyLebeau Have you ever used c++builder6 debugger?

– Krzysztof Szewczyk
Apr 25 '17 at 15:08





@RemyLebeau Have you ever used c++builder6 debugger?

– Krzysztof Szewczyk
Apr 25 '17 at 15:08













All the time. BCB6 is the compiler I have to use at my day job :-( But the issue you describe is not limited to just BCB6. You have errors in your code, so it would be broken in any compiler version.

– Remy Lebeau
Apr 25 '17 at 15:11







All the time. BCB6 is the compiler I have to use at my day job :-( But the issue you describe is not limited to just BCB6. You have errors in your code, so it would be broken in any compiler version.

– Remy Lebeau
Apr 25 '17 at 15:11















bcb6 debugger shown me error at end of caller procedure.

– Krzysztof Szewczyk
Apr 25 '17 at 15:19





bcb6 debugger shown me error at end of caller procedure.

– Krzysztof Szewczyk
Apr 25 '17 at 15:19













There are errors in your code, starting with the very first line of your interpret() function. Do you understand WHY that line of code is faulty? You are taking a pointer to temporary data that gets freed immediately after you take the pointer, so the subsequent lines of code are operating on invalid memory. There is another memory error in your ',' handler - you are trying to copying data to an uninitialized pointer that is not pointing at valid memory.

– Remy Lebeau
Apr 25 '17 at 15:33







There are errors in your code, starting with the very first line of your interpret() function. Do you understand WHY that line of code is faulty? You are taking a pointer to temporary data that gets freed immediately after you take the pointer, so the subsequent lines of code are operating on invalid memory. There is another memory error in your ',' handler - you are trying to copying data to an uninitialized pointer that is not pointing at valid memory.

– Remy Lebeau
Apr 25 '17 at 15:33














1 Answer
1






active

oldest

votes


















2














There are memory-related errors in your code. The very first line of interpret() is taking a pointer to a temporary AnsiString that is freed immediately afterwards, so the subsequent lines of code are operating with a dangling pointer to invalid memory. Likewise, in your ',' handler, you are trying to copy data to an uninitialized pointer that is not pointing at valid memory. And you are not doing any bounds checking when accessing your cells array.



There are also logic errors in your ']' handler. You are not checking the current cell data for 0 to decide which instruction to jump to next, and you are not seeking backwards correctly when looking for the opening '['.



Try something more like this instead:



static const int maxCells = 65536;

class BFIde : public TForm
{
__published:
TEdit *Edit2;
TMemo *Memo1;
TMemo *Memo2;
TButton *Button1;
void __fastcall Button1(TObject *Sender);
private:
char cells[maxCells];
int cellp;
char& cellData();
void __fastcall interpret(const AnsiString &commands, AnsiString input);
public:
__fastcall BFIde(TComponent *Owner);
};




__fastcall BFIde::BFIde(TComponent *Owner)
: TForm(Owner)
{
}

char& __fastcall BFIde::cellData()
{
if ((cellp < 0) or (cellp >= maxCells))
throw Exception("Accessing cells out of bounds");
return cells[cellp];
}

void __fastcall BFIde::interpret(const AnsiString &commands, AnsiString input)
{
Memo1->Clear();

memset(cells, 0, maxCells);
cellp = 0;

const char* start = commands.c_str();
const char* p = start;

while (*p)
{
switch (*p)
{
case '>':
++cellp;
break;

case '<':
--cellp;
break;

case '+':
cellData()++;
break;

case '-':
cellData()--;
break;

case '.':
{
char ch = cellData();
Memo1->SelStart = Memo1->GetTextLen();
Memo1->SelLength = 0;
Memo1->SelText = ch;
break;
}

case ',':
{
char ch;
if (input.Length() == 0) {
ch = '';
}
else {
ch = input[1];
input.Delete(1, 1);
}
cellData() = ch;
break;
}

case '[':
{
if (cellData() == '')
{
int bal = 1;
while (*++p)
{
if (*p == '[') {
++bal;
}
else if (*p == ']')
{
if (--bal == 0)
break;
}
}
if (bal != 0)
throw Exception("Unbalanced loop");
}
break;
}

case ']':
{
if (cellData() != '')
{
int bal = 1;
while (p > start)
{
--p;
if (*p == ']') {
++bal;
}
else if (*p == '[')
{
if (--bal == 0)
break;
}
}
if (bal != 0)
throw Exception("Unbalanced loop");
}
break;
}
}

++p;
}

ShowMessage(cellp);
}

void __fastcall BFIde::Button1(TObject *Sender)
{
interpret(Memo2->Lines->Text, Edit2->Text);
}





share|improve this answer


























  • I didn't know about GetTextLen(), your code is ok. Thank you very much.

    – Krzysztof Szewczyk
    Apr 26 '17 at 14:00











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f43558399%2fbrainfuck-interpreter-strange-output%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














There are memory-related errors in your code. The very first line of interpret() is taking a pointer to a temporary AnsiString that is freed immediately afterwards, so the subsequent lines of code are operating with a dangling pointer to invalid memory. Likewise, in your ',' handler, you are trying to copy data to an uninitialized pointer that is not pointing at valid memory. And you are not doing any bounds checking when accessing your cells array.



There are also logic errors in your ']' handler. You are not checking the current cell data for 0 to decide which instruction to jump to next, and you are not seeking backwards correctly when looking for the opening '['.



Try something more like this instead:



static const int maxCells = 65536;

class BFIde : public TForm
{
__published:
TEdit *Edit2;
TMemo *Memo1;
TMemo *Memo2;
TButton *Button1;
void __fastcall Button1(TObject *Sender);
private:
char cells[maxCells];
int cellp;
char& cellData();
void __fastcall interpret(const AnsiString &commands, AnsiString input);
public:
__fastcall BFIde(TComponent *Owner);
};




__fastcall BFIde::BFIde(TComponent *Owner)
: TForm(Owner)
{
}

char& __fastcall BFIde::cellData()
{
if ((cellp < 0) or (cellp >= maxCells))
throw Exception("Accessing cells out of bounds");
return cells[cellp];
}

void __fastcall BFIde::interpret(const AnsiString &commands, AnsiString input)
{
Memo1->Clear();

memset(cells, 0, maxCells);
cellp = 0;

const char* start = commands.c_str();
const char* p = start;

while (*p)
{
switch (*p)
{
case '>':
++cellp;
break;

case '<':
--cellp;
break;

case '+':
cellData()++;
break;

case '-':
cellData()--;
break;

case '.':
{
char ch = cellData();
Memo1->SelStart = Memo1->GetTextLen();
Memo1->SelLength = 0;
Memo1->SelText = ch;
break;
}

case ',':
{
char ch;
if (input.Length() == 0) {
ch = '';
}
else {
ch = input[1];
input.Delete(1, 1);
}
cellData() = ch;
break;
}

case '[':
{
if (cellData() == '')
{
int bal = 1;
while (*++p)
{
if (*p == '[') {
++bal;
}
else if (*p == ']')
{
if (--bal == 0)
break;
}
}
if (bal != 0)
throw Exception("Unbalanced loop");
}
break;
}

case ']':
{
if (cellData() != '')
{
int bal = 1;
while (p > start)
{
--p;
if (*p == ']') {
++bal;
}
else if (*p == '[')
{
if (--bal == 0)
break;
}
}
if (bal != 0)
throw Exception("Unbalanced loop");
}
break;
}
}

++p;
}

ShowMessage(cellp);
}

void __fastcall BFIde::Button1(TObject *Sender)
{
interpret(Memo2->Lines->Text, Edit2->Text);
}





share|improve this answer


























  • I didn't know about GetTextLen(), your code is ok. Thank you very much.

    – Krzysztof Szewczyk
    Apr 26 '17 at 14:00
















2














There are memory-related errors in your code. The very first line of interpret() is taking a pointer to a temporary AnsiString that is freed immediately afterwards, so the subsequent lines of code are operating with a dangling pointer to invalid memory. Likewise, in your ',' handler, you are trying to copy data to an uninitialized pointer that is not pointing at valid memory. And you are not doing any bounds checking when accessing your cells array.



There are also logic errors in your ']' handler. You are not checking the current cell data for 0 to decide which instruction to jump to next, and you are not seeking backwards correctly when looking for the opening '['.



Try something more like this instead:



static const int maxCells = 65536;

class BFIde : public TForm
{
__published:
TEdit *Edit2;
TMemo *Memo1;
TMemo *Memo2;
TButton *Button1;
void __fastcall Button1(TObject *Sender);
private:
char cells[maxCells];
int cellp;
char& cellData();
void __fastcall interpret(const AnsiString &commands, AnsiString input);
public:
__fastcall BFIde(TComponent *Owner);
};




__fastcall BFIde::BFIde(TComponent *Owner)
: TForm(Owner)
{
}

char& __fastcall BFIde::cellData()
{
if ((cellp < 0) or (cellp >= maxCells))
throw Exception("Accessing cells out of bounds");
return cells[cellp];
}

void __fastcall BFIde::interpret(const AnsiString &commands, AnsiString input)
{
Memo1->Clear();

memset(cells, 0, maxCells);
cellp = 0;

const char* start = commands.c_str();
const char* p = start;

while (*p)
{
switch (*p)
{
case '>':
++cellp;
break;

case '<':
--cellp;
break;

case '+':
cellData()++;
break;

case '-':
cellData()--;
break;

case '.':
{
char ch = cellData();
Memo1->SelStart = Memo1->GetTextLen();
Memo1->SelLength = 0;
Memo1->SelText = ch;
break;
}

case ',':
{
char ch;
if (input.Length() == 0) {
ch = '';
}
else {
ch = input[1];
input.Delete(1, 1);
}
cellData() = ch;
break;
}

case '[':
{
if (cellData() == '')
{
int bal = 1;
while (*++p)
{
if (*p == '[') {
++bal;
}
else if (*p == ']')
{
if (--bal == 0)
break;
}
}
if (bal != 0)
throw Exception("Unbalanced loop");
}
break;
}

case ']':
{
if (cellData() != '')
{
int bal = 1;
while (p > start)
{
--p;
if (*p == ']') {
++bal;
}
else if (*p == '[')
{
if (--bal == 0)
break;
}
}
if (bal != 0)
throw Exception("Unbalanced loop");
}
break;
}
}

++p;
}

ShowMessage(cellp);
}

void __fastcall BFIde::Button1(TObject *Sender)
{
interpret(Memo2->Lines->Text, Edit2->Text);
}





share|improve this answer


























  • I didn't know about GetTextLen(), your code is ok. Thank you very much.

    – Krzysztof Szewczyk
    Apr 26 '17 at 14:00














2












2








2







There are memory-related errors in your code. The very first line of interpret() is taking a pointer to a temporary AnsiString that is freed immediately afterwards, so the subsequent lines of code are operating with a dangling pointer to invalid memory. Likewise, in your ',' handler, you are trying to copy data to an uninitialized pointer that is not pointing at valid memory. And you are not doing any bounds checking when accessing your cells array.



There are also logic errors in your ']' handler. You are not checking the current cell data for 0 to decide which instruction to jump to next, and you are not seeking backwards correctly when looking for the opening '['.



Try something more like this instead:



static const int maxCells = 65536;

class BFIde : public TForm
{
__published:
TEdit *Edit2;
TMemo *Memo1;
TMemo *Memo2;
TButton *Button1;
void __fastcall Button1(TObject *Sender);
private:
char cells[maxCells];
int cellp;
char& cellData();
void __fastcall interpret(const AnsiString &commands, AnsiString input);
public:
__fastcall BFIde(TComponent *Owner);
};




__fastcall BFIde::BFIde(TComponent *Owner)
: TForm(Owner)
{
}

char& __fastcall BFIde::cellData()
{
if ((cellp < 0) or (cellp >= maxCells))
throw Exception("Accessing cells out of bounds");
return cells[cellp];
}

void __fastcall BFIde::interpret(const AnsiString &commands, AnsiString input)
{
Memo1->Clear();

memset(cells, 0, maxCells);
cellp = 0;

const char* start = commands.c_str();
const char* p = start;

while (*p)
{
switch (*p)
{
case '>':
++cellp;
break;

case '<':
--cellp;
break;

case '+':
cellData()++;
break;

case '-':
cellData()--;
break;

case '.':
{
char ch = cellData();
Memo1->SelStart = Memo1->GetTextLen();
Memo1->SelLength = 0;
Memo1->SelText = ch;
break;
}

case ',':
{
char ch;
if (input.Length() == 0) {
ch = '';
}
else {
ch = input[1];
input.Delete(1, 1);
}
cellData() = ch;
break;
}

case '[':
{
if (cellData() == '')
{
int bal = 1;
while (*++p)
{
if (*p == '[') {
++bal;
}
else if (*p == ']')
{
if (--bal == 0)
break;
}
}
if (bal != 0)
throw Exception("Unbalanced loop");
}
break;
}

case ']':
{
if (cellData() != '')
{
int bal = 1;
while (p > start)
{
--p;
if (*p == ']') {
++bal;
}
else if (*p == '[')
{
if (--bal == 0)
break;
}
}
if (bal != 0)
throw Exception("Unbalanced loop");
}
break;
}
}

++p;
}

ShowMessage(cellp);
}

void __fastcall BFIde::Button1(TObject *Sender)
{
interpret(Memo2->Lines->Text, Edit2->Text);
}





share|improve this answer















There are memory-related errors in your code. The very first line of interpret() is taking a pointer to a temporary AnsiString that is freed immediately afterwards, so the subsequent lines of code are operating with a dangling pointer to invalid memory. Likewise, in your ',' handler, you are trying to copy data to an uninitialized pointer that is not pointing at valid memory. And you are not doing any bounds checking when accessing your cells array.



There are also logic errors in your ']' handler. You are not checking the current cell data for 0 to decide which instruction to jump to next, and you are not seeking backwards correctly when looking for the opening '['.



Try something more like this instead:



static const int maxCells = 65536;

class BFIde : public TForm
{
__published:
TEdit *Edit2;
TMemo *Memo1;
TMemo *Memo2;
TButton *Button1;
void __fastcall Button1(TObject *Sender);
private:
char cells[maxCells];
int cellp;
char& cellData();
void __fastcall interpret(const AnsiString &commands, AnsiString input);
public:
__fastcall BFIde(TComponent *Owner);
};




__fastcall BFIde::BFIde(TComponent *Owner)
: TForm(Owner)
{
}

char& __fastcall BFIde::cellData()
{
if ((cellp < 0) or (cellp >= maxCells))
throw Exception("Accessing cells out of bounds");
return cells[cellp];
}

void __fastcall BFIde::interpret(const AnsiString &commands, AnsiString input)
{
Memo1->Clear();

memset(cells, 0, maxCells);
cellp = 0;

const char* start = commands.c_str();
const char* p = start;

while (*p)
{
switch (*p)
{
case '>':
++cellp;
break;

case '<':
--cellp;
break;

case '+':
cellData()++;
break;

case '-':
cellData()--;
break;

case '.':
{
char ch = cellData();
Memo1->SelStart = Memo1->GetTextLen();
Memo1->SelLength = 0;
Memo1->SelText = ch;
break;
}

case ',':
{
char ch;
if (input.Length() == 0) {
ch = '';
}
else {
ch = input[1];
input.Delete(1, 1);
}
cellData() = ch;
break;
}

case '[':
{
if (cellData() == '')
{
int bal = 1;
while (*++p)
{
if (*p == '[') {
++bal;
}
else if (*p == ']')
{
if (--bal == 0)
break;
}
}
if (bal != 0)
throw Exception("Unbalanced loop");
}
break;
}

case ']':
{
if (cellData() != '')
{
int bal = 1;
while (p > start)
{
--p;
if (*p == ']') {
++bal;
}
else if (*p == '[')
{
if (--bal == 0)
break;
}
}
if (bal != 0)
throw Exception("Unbalanced loop");
}
break;
}
}

++p;
}

ShowMessage(cellp);
}

void __fastcall BFIde::Button1(TObject *Sender)
{
interpret(Memo2->Lines->Text, Edit2->Text);
}






share|improve this answer














share|improve this answer



share|improve this answer








edited Apr 26 '17 at 17:32

























answered Apr 25 '17 at 17:06









Remy LebeauRemy Lebeau

334k18253448




334k18253448













  • I didn't know about GetTextLen(), your code is ok. Thank you very much.

    – Krzysztof Szewczyk
    Apr 26 '17 at 14:00



















  • I didn't know about GetTextLen(), your code is ok. Thank you very much.

    – Krzysztof Szewczyk
    Apr 26 '17 at 14:00

















I didn't know about GetTextLen(), your code is ok. Thank you very much.

– Krzysztof Szewczyk
Apr 26 '17 at 14:00





I didn't know about GetTextLen(), your code is ok. Thank you very much.

– Krzysztof Szewczyk
Apr 26 '17 at 14:00


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f43558399%2fbrainfuck-interpreter-strange-output%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

404 Error Contact Form 7 ajax form submitting

How to know if a Active Directory user can login interactively

Refactoring coordinates for Minecraft Pi buildings written in Python