Mysterious "ghost definition" of a user-defined function

My boss wants me to work on this code and I made it through almost all the bug fixes and ran into a peculiar set of errors:

gort_killswitch:28: error: 'Output' was not declared in this scope
gort_killswitch:28: error: 'RepCheck' was not declared in this scope
gort_killswitch:28: error: initializer expression list treated as compound expression
gort_killswitch:48: error: redefinition of 'boolean Close'
gort_killswitch:28: error: 'boolean Close' previously defined here

It's very odd because the function Close(Output,Repcheck) is defined for the first time on line 48, but the debugger clearly believes it was defined on line 28 and then redefined on line 48. When I use /* */ to comment out lines 27 through 29 the error persists. In different iterations of the code it has chosen entirely different and equally random lines for its "ghost definition." The first error tells me that the "ghost definition" occurs before the definition of the variables which actually occurs on line 28.

Here is the code; I have put lines of slashes before what would be lines 28 and 48 to make them easy to find.

//
//  deadman1.c
// 
//
//  Created by Kevin McLin on 9/2/14.
//
//

/*
this program will read a few pins on the serial connector between GORT's control
PC and the dome, and, if the control PC dies, close the dome to protect the equipment
inside.
 
assumptions:
DE9 pin4 is 6.8V when PC is alive and 6.4V when PC is dead
arduino will accurately read return codes from dome
this circuit will not interfere with signals from PC to dome when PC is alive
arduino RX/TX pins are connected to DE9 RX/TX pin on serial shield
 
hardware description:
DE9 pin4 is connected to arduino analog pin0 by a 100? resistor
analog pin0 is connected to ground by a 100? resistor
analog read ADC values roughly equal 102.4*V
*/

boolean DomeOpen = true;
boolean DomeClosed; // Flag for failure of dome to close. Return state of closeDome. This is just for diagnostics.

///////////////////////   28   ////////////////////////////////////////////////////////////////////////////

int Output; // Value to send to the dome control hardware.
int RepCheck; // Value to check against reply value of the dome control hardware.
boolean IsDead()
/*
 This function checks to see if the dome controller is alive. If the software crashes or the computer goes down,
 the voltage on Pin4 of the serial line will drop from 6.8 volts to to 6.4 volts. This voltage is read by the Arduino
 A0 pin through a 100 Ohm resister. This causes the voltage on that pin to be either above 3.3V if the dome
 controller is alive, and below 3.3V if the controller is dead. The function checks the ADU value that corresponds
 to 3.3V, which is 675.
*/
  {
  if (analogRead(0) <= 675) // if the DE9 pin4 is below 3.3V
    {
    return true; // Dome controller is not running.
    }
  else 
    {
    return false; // Dome controller is running.
    }
  }

///////////////////////   48   ////////////////////////////////////////////////////////////////////////////

boolean Close(Output,RepCheck)
/*
 This function opens a serial connection to the dome and then closes one side of the dome; which side depends on the inputs.
 It then closes the serial connection and exits
*/
  {
  boolean Open = true; // Assume condition of dome shell is open when we begin.
  int Reply; // Reply value of the dome controller.
  while (Open) // Loop until the dome reports being closed.
    {
    Serial.write(output); // arduino will tell the dome to close.
    Reply = Serial.read(); // Read the reply of the dome controller.
    if (Reply == RepCheck) // if the dome says it's closed, return.
      {
      return true; // Return with success indicated.
      }
    else if (Reply == RepCheck + 32 ) // Dome is still closing.
      {
      continue;
      }
    else
      {
      return false; // This shouldn't happen. Return with failure.
      }
    }
  }



void setup()
  {
  Serial.begin(9600);
  }

/*
 Need to check that the dome is closed successfully and not just assume it has. This will require some additional
 code to check for exceptions in the close function.
*/



void loop()
  {
  if (IsDead && DomeOpen)
    {
    DomeClosed = CloseDome; // Close the dome. Should put a check in this function to verify success.
    DomeOpen = false; // This should only be set to false if the closeDome procedure was successful.
    }
  }

you are defining a function but not declaring what the values passed are (e.g int, float, etc)

boolean Close(Output,RepCheck)

{
  boolean Open = true; // Assume condition of dome shell is open when we begin.
  int Reply; // Reply value of the dome controller.
  while (Open) // Loop until the dome reports being closed.
  {
    Serial.write(output); // arduino will tell the dome to close.
    Reply = Serial.read(); // Read the reply of the dome controller.
    if (Reply == RepCheck) // if the dome says it's closed, return.
    {
      return true; // Return with success indicated.
    }
    else if (Reply == RepCheck + 32 ) // Dome is still closing.
    {
      continue;
    }
    else
    {
      return false; // This shouldn't happen. Return with failure.
    }
  }
}

a typical function defiition:

boolean Close (int myInt , int myOtherInt)

Plus,

Serial.write(output);

Is not the same as Output, hopefully just a typo.

And the compiler doesn't know what "CloseDome;" is.

Also, I wasn't aware this worked:

if (IsDead && DomeOpen) // Somehow IsDead works even though it is not written as IsDead()
{
DomeClosed = CloseDome; // Close the dome. Should put a check in this function to verify success.
DomeOpen = false; // This should only be set to false if the closeDome procedure was successful.
}

void loop()
  {
  if (IsDead && DomeOpen)

What's the type of IsDead ? a boolean or a function that returns a boolean

Mark

One of the problems is that the variables Output and RepCheck are declared globally but then passed to the close function as (incorrectly specified) arguments. Change the declaration of Close to:

boolean Close(void)

so that Close will use the global variables Output and RepCheck.

You've got several other syntax errors to fix as well. For example, in the Close function you have:

Serial.write(output);

which presumably should be:

Serial.write(Output);

There's really no point to having this statement in Close():

while (Open)

This will work just as well if you remove the declaration of Open and change the while to:

while (1)

There are others but I'll let you earn some of your paycheque :slight_smile:

Pete

This statement:

  if (IsDead && DomeOpen)

is a good example of why you should have "verbose output after compilation" set in your preferences.
Then read and understand what the warning messages are telling you. In this case:

sketch_sep08a.ino: In function 'void loop()':
sketch_sep08a.ino:97:17: warning: the address of 'boolean IsDead()' will always evaluate as 'true' [-Waddress]

'isDead' is the address of the boolean function isDead(). In other words, the function isn't being called correctly.

Pete

Note also that:

boolean IsDead()
  {
  if (analogRead(0) <= 675) // if the DE9 pin4 is below 3.3V
    {
    return true; // Dome controller is not running.
    }
  else 
    {
    return false; // Dome controller is running.
    }
  }

contracts to

boolean IsDead(){
return (analogRead(0) <= 675);
}

Hardly worth using a function for.

Hardly worth using a function for.

I disagree. IsDead() clearly suggests some meaning that analogRead(0) <= 675 does not.

When looking at the (properly written) code, IsDead() has far more meaning than analogRead(0) <= 675. Once one knows that the author of the function is reading from the correct pin, and has correctly chosen the limit value, then the actual working of the function can be ignored.

PaulS:

Hardly worth using a function for.

I disagree. IsDead() clearly suggests some meaning that analogRead(0) <= 675 does not.

A clear and concise comment would suggest exactly the same.
E.g. //Is it dead?

boolean Close(Output,RepCheck)

This is invalid. You need to specify the type or class of those function arguments.