Problem with release build of program using pointers


C

Cam

Hi all,

The code below is a practical exercise and works well running in the debug
environment but fails when being compiled for a release build. I believe
this is because the debug environment takes care of memory allocation and
the release build relies on code to do this. My research in my books and on
the web has not provided any great help.

I would be grateful for advice on what I need to do to correctly allocate
the memory resources for the code to compile correctly to release as an .exe
program.

Cheers,

Cam

Code follows:

#include <iostream>
#include <conio.h>

using namespace std;

KeyboardInput(int *pkey); // Gathers input
Add1Comp(int *presult); // Carries out addition

int key1[8], carrykey1[8], key2[8], carrykey2[8], result[8];

int main (int *pkey) ////////////////////////////////////////////// main()
///////////////////////////////////////////////////////////
{
do
{
KeyboardInput(key1); // Calls KeyboardInput whose ouput is key1
KeyboardInput(key2); // Calls KeyboardInput whose output is key2
Add1Comp(result); // Calls Add1Comp whose output is result
}
while(1);
return 0;
}

int KeyboardInput (int *pkey) //////////////////////////// KeyboardInput()
/////////////////////////////////////////////
{
restart:
int counter = 0;
cout << "\nEnter an 8 bit binary number: ";
for (counter = 8; counter > 0; counter --)
{
pkey[counter] = (getche() - 48);
}
cout << "\n";
for (counter = 8; counter > 0; counter --)
{
if (pkey[counter] != 0 && pkey[counter] != 1)
{
cout << "\n\nYou have entered non-binary character. Please
restart\n\n";
goto restart;
}
}
return 0;
}

int Add1Comp (int *presult) /////////////////////////// Add1Comp()
/////////////////////////////////////////////////
{
int latch = 0;
restart:
int counter, carry = 0;
for (counter = 1; counter < 9; counter ++)
{
switch (key1[counter] + key2[counter] + carry)
{
case 0: // 0+0+0 = 0 carry 0
presult[counter] = 0;
cout << "\nBit " << counter << ": " << key1[counter] << " + " <<
key2[counter] << " + " << carry << " = " << presult[counter] << " carry ";
carry = 0;
cout << carry;
break;
case 1: // 0+0+1 xor 0+1+0 xor 1+0+0 = 1 carry 0
presult[counter] = 1;
cout << "\nBit " << counter << ": " << key1[counter] << " + " <<
key2[counter] << " + " << carry << " = " << presult[counter] << " carry ";
carry = 0;
cout << carry;
break;
case 2: // 1+1+0 xor 1+0+1 xor 0+1+1 = 0 carry 1
presult[counter] = 0;
cout << "\nBit " << counter << ": " << key1[counter] << " + " <<
key2[counter] << " + " << carry << " = " << presult[counter] << " carry ";
carry = 1;
cout << carry;
break;
case 3: // 1+1+1 = 1 carry 1
presult[counter] = 1;
cout << "\nBit " << counter << ": " << key1[counter] << " + " <<
key2[counter] << " + " << carry << " = " << presult[counter] << " carry ";
carry = 1;
cout << carry;
break;
}
if (counter == 8 && carry == 1)
goto addcarry;
if (counter == 8 && latch == 1 && carry == 1)
goto overflow;
}
cout << "\n\nResult of ";
for (counter = 8; counter > 0; counter --)
{
if (latch)
key1[counter] = carrykey1[counter];
cout << key1[counter];
}
cout << " + ";
for (counter = 8; counter > 0; counter --)
{
if (latch)
key2[counter] = carrykey2[counter];
cout << key2[counter];
}
cout << " = ";
for (counter = 8; counter > 0; counter --)
{
cout << presult[counter];
}
cout << "\n\n-----------------------------------------\n";
latch = 0;
return 0;

addcarry:
latch = 1;
cout << "\n\nAdd final carry:\n";
for (counter = 1; counter < 9; counter ++)
{
carrykey1[counter] = key1[counter];
key1[counter] = result[counter];
carrykey2[counter] = key2[counter];
key2[counter] = 0;
presult[counter] = 0;
}
key2[1] = 1;
goto restart;
overflow:
cout << "\nThe addition has resulted in an overflow";
main(key1);
}
 
Ad

Advertisements

M

Mike Wahler

Cam said:
Hi all,

The code below is a practical exercise and works well running in the debug
environment but fails when being compiled for a release build. I believe
this is because the debug environment takes care of memory allocation and
the release build relies on code to do this. My research in my books and on
the web has not provided any great help.

Your code doesn't do any allocations.
But it does produce undefined behavior.
See below.
I would be grateful for advice on what I need to do to correctly allocate
the memory resources for the code to compile correctly to release as an ..exe
program.

Cheers,

Cam

Code follows:

#include <iostream>
#include <conio.h>

This is a nonstandard header. Please omit such
from code posted here.
using namespace std;

KeyboardInput(int *pkey); // Gathers input
Add1Comp(int *presult); // Carries out addition

int key1[8], carrykey1[8], key2[8], carrykey2[8], result[8];

Each of these arrays has eight elements. Therefore the
valid range of subscripts for each is from zero through seven.
int main (int *pkey) ////////////////////////////////////////////// main()

If you use them, main()'s first two arguments must
be type 'int', and 'char **', respectively.
///////////////////////////////////////////////////////////
{
do
{
KeyboardInput(key1); // Calls KeyboardInput whose ouput is key1
KeyboardInput(key2); // Calls KeyboardInput whose output is key2
Add1Comp(result); // Calls Add1Comp whose output is result
}
while(1);
return 0;
}

int KeyboardInput (int *pkey) //////////////////////////// KeyboardInput()
/////////////////////////////////////////////
{
restart:
int counter = 0;
cout << "\nEnter an 8 bit binary number: ";
for (counter = 8; counter > 0; counter --)

'counter' starts out with a value of 8.
{
pkey[counter] = (getche() - 48);

Element eight is out of bound for your arrays 'key1' and
'key2' above, whose addresses you've passed to this function.
This gives 'undefined behavior'.

Also not that 'getche()' is a nonstandard function.
Please omit such from code posted here.
}
cout << "\n";
for (counter = 8; counter > 0; counter --)
{
if (pkey[counter] != 0 && pkey[counter] != 1)

And again.
{
cout << "\n\nYou have entered non-binary character. Please
restart\n\n";
goto restart;

Consider using a loop instead of a 'goto'.
}
}
return 0;
}

int Add1Comp (int *presult) /////////////////////////// Add1Comp()
/////////////////////////////////////////////////
{
int latch = 0;
restart:
int counter, carry = 0;
for (counter = 1; counter < 9; counter ++)

You have the same problems here. Array indices are
from zero the the number of elements less one.

for (counter = 0; counter < 8; counter ++)

More below.
{
switch (key1[counter] + key2[counter] + carry)
{
case 0: // 0+0+0 = 0 carry 0
presult[counter] = 0;
cout << "\nBit " << counter << ": " << key1[counter] << " + " <<
key2[counter] << " + " << carry << " = " << presult[counter] << " carry ";
carry = 0;
cout << carry;
break;
case 1: // 0+0+1 xor 0+1+0 xor 1+0+0 = 1 carry 0
presult[counter] = 1;
cout << "\nBit " << counter << ": " << key1[counter] << " + " <<
key2[counter] << " + " << carry << " = " << presult[counter] << " carry ";
carry = 0;
cout << carry;
break;
case 2: // 1+1+0 xor 1+0+1 xor 0+1+1 = 0 carry 1
presult[counter] = 0;
cout << "\nBit " << counter << ": " << key1[counter] << " + " <<
key2[counter] << " + " << carry << " = " << presult[counter] << " carry ";
carry = 1;
cout << carry;
break;
case 3: // 1+1+1 = 1 carry 1
presult[counter] = 1;
cout << "\nBit " << counter << ": " << key1[counter] << " + " <<
key2[counter] << " + " << carry << " = " << presult[counter] << " carry ";
carry = 1;
cout << carry;
break;
}
if (counter == 8 && carry == 1)
goto addcarry;
if (counter == 8 && latch == 1 && carry == 1)
goto overflow;
}
cout << "\n\nResult of ";
for (counter = 8; counter > 0; counter --)
{
if (latch)
key1[counter] = carrykey1[counter];
cout << key1[counter];
}
cout << " + ";
for (counter = 8; counter > 0; counter --)
{
if (latch)
key2[counter] = carrykey2[counter];
cout << key2[counter];
}
cout << " = ";
for (counter = 8; counter > 0; counter --)
{
cout << presult[counter];
}
cout << "\n\n-----------------------------------------\n";
latch = 0;
return 0;

addcarry:
latch = 1;
cout << "\n\nAdd final carry:\n";
for (counter = 1; counter < 9; counter ++)
{
carrykey1[counter] = key1[counter];
key1[counter] = result[counter];
carrykey2[counter] = key2[counter];
key2[counter] = 0;
presult[counter] = 0;
}
key2[1] = 1;
goto restart;
overflow:
cout << "\nThe addition has resulted in an overflow";
main(key1);

'main()' may not be called recursively in C++.

You're probably correct that your implementation's 'debug
mode' was 'protecting' you from a crash.

-Mike
 
V

Victor Bazarov

Cam said:
The code below is a practical exercise and works well [...]

Which is not surprising. Your code is full of parts that cause
undefined behaviour. One of possible behaviours is "to work as
expected". Another is "not to work as expected". You apparently
witnessed both, one in debug the other in release mode. They did
not have to be particularly that. They could have been vice versa
or both the same. It's impossible to predict because it's simply
_undefined_.

As soon as you fix it to comply with C++ Standard, you might be
surprised that it works always...

To be specific, check out what indices you used to access your
8-element arrays. Think of the correct range in that case and
verify that your indices always fall in that range...

Good luck!

V
 
J

John Harrison

Cam said:
Hi all,

The code below is a practical exercise and works well running in the debug
environment but fails when being compiled for a release build. I believe
this is because the debug environment takes care of memory allocation and
the release build relies on code to do this.

That's untrue.

john
 
C

Cam

Hi John,

Thank you for your help previously.

The fact that my arrays start with an element at position 1 doesn't seem to
cause problems in the debug environment.

Is this is what is preventing the code from undergoing a release build?

Thanks,

Cam


|
| "Cam" <retsigerymmudathotmaildotcom> wrote in message
| | > Hi all,
| >
| > The code below is a practical exercise and works well running in the
debug
| > environment but fails when being compiled for a release build. I believe
| > this is because the debug environment takes care of memory allocation
and
| > the release build relies on code to do this.
|
| That's untrue.
|
| john
|
|
 
Ad

Advertisements

J

John Harrison

Cam said:
Hi John,

Thank you for your help previously.

The fact that my arrays start with an element at position 1 doesn't seem to
cause problems in the debug environment.

Is this is what is preventing the code from undergoing a release build?

Yes, arrays start at position 0 in C++, that applies to debug builds,
release builds, different compilers, everything.

As others explained you program has undefined behaviour. And undefined
behaviour means anything can happen, including working in the debug build
and not working in the release build.

If you change your program so that it does not have undefined behaviour,
then it will work in any build.

john
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top