why do compiler errors refer to wrong places in code?

I get some compile/link errors that refer to line numbers in my source file that seem to be 100% unrelated to the problem. I understand well how syntax errors (such as missing delimiters etc) in one place are often only caught later in the code.. but this does not seem to be the case here.
Note how the errors refer to lines 15 and 33 (marked in the code below):

Arduino: 1.8.7 (Windows 10), Board: "NodeMCU 1.0 (ESP-12E Module), 80 MHz, Flash, 4M (1M SPIFFS), v2 Lower Memory, Disabled, WIFI, Only Sketch, 115200"

sketch\smallsteps.ino.cpp.o: In function `printWifiStatus()':

C:\Ard\Ceiling\RemoteSign\smallsteps/smallsteps.ino:15: undefined reference to `RemoteSign::setChannelData(int, char, int, bool)'

sketch\smallsteps.ino.cpp.o: In function `setup':

C:\Ard\Ceiling\RemoteSign\smallsteps/smallsteps.ino:33: undefined reference to `RemoteSign::setChannelData(int, char, int, bool)'

collect2.exe: error: ld returned 1 exit status

exit status 1
Error compiling for board NodeMCU 1.0 (ESP-12E Module).

and here is the code:

#include "ESP8266WiFi.h"
#include "RemoteSign.h"
#include "Ceiling.h"

#define DEFAULT_BRI  80

void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("\nSSID: ");

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print(" IP Address: ");
  Serial.print(ip);      // line 15  ==============

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print(" signal strength (RSSI):");
  Serial.println(" dBm");

void setup() {
  // switch a string of lights to DEFAULT_BRI right away
 // setChannel(1,DEFAULT_BRI*10.23);
  // get onto wifi
  WiFi.begin(ssid, password);
  Serial.println(ssid); // throw out network SSID        // line 33 ============
  while (WiFi.status() != WL_CONNECTED) { delay(250); Serial.print(".");  }  printWifiStatus(); 
  // switch second string of lights to DEFAULT_BRI after connecting
//  setChannel(2,DEFAULT_BRI*10.23);

 // set up RemoteSign 
 RemoteSign rs;  
 rs.setCH("{CH}1\21M\21D\r{CH}2\21M\21D\r{CH}3\21M\21D\r{CH}4\21M\r"); // \21 is octal for 17 decimal (DC1)

 // define channel data (0 based)
  rs.setChannelData(1,'M',4,true);   // this is the line with the problem. If I comment it out it compiles.
 // rs.setChannelData(2,'M',5,true);
 // rs.setChannelData(3,'M',12,true);
 // rs.setChannelData(4,'M',13,false);
 rs.begin(); // start server listening 

void loop() {

} // loop()
  while (WiFi.status() != WL_CONNECTED) { delay(250); Serial.print(".");  }  printWifiStatus();

Fix your own layout before complaining about the compiler.

Like I said the line number have absolutely nothing to do with the code at the lines it refers to.

Hence, it has nothing to do with how many statement I place on a line. If C insists on line terminators I may use them.

If I add line elsewhere it shifts to another line.

If you cant handle my line 33 ignore it and explain line 15.


The thing is that Arduino adds extra stuff to your code before sending it to the compiler. There’s guides that it gives to the compiler to tell it that line came from file at line number . But that’s not always possible.

Since you’ve got many things on one line that others consider to be multiple lines, you can’t really tell what Arduino and the compiler did to your code when it counted “33”.

To expand on what MorganS replied while I was writing this:

When you compile a sketch, the Arduino IDE does some preprocessing on the sketch .ino files to make them valid C++. One of these steps is to add function prototypes for any function in the sketch that doesn’t already have one. Those inserted lines of code change the line numbers of the sketch. The Arduino IDE adds #line directives to make it so the line numbers match your sketch. It’s possible that something went wrong with these automatically generated #line directives. I can’t say for sure, because I don’t have all the files needed to compile your sketch.

When you encounter a strange error like this, it’s a good idea to take a look at the preprocessed sketch code. That is stored in the temporary build folder.

  • File > Preferences > Show verbose output during: compile (check) > OK
  • Sketch > Verify/Compile

After the compilation fails, scroll up the black console window at the bottom of the Arduino IDE window and examine the output to find the location of the temporary build folder. You will find it on the first line of the output following the -build-path option passed to arduino-builder. For example, it might look something like this:

C:\ArduinoIDE\arduino-1.8.8\arduino-builder -dump-prefs -logger=machine -hardware C:\ArduinoIDE\arduino-1.8.8\hardware -hardware C:\Users\per\AppData\Local\Arduino15\packages -hardware E:\electronics\arduino\hardware -tools C:\ArduinoIDE\arduino-1.8.8\tools-builder -tools C:\ArduinoIDE\arduino-1.8.8\hardware\tools\avr -tools C:\Users\per\AppData\Local\Arduino15\packages -built-in-libraries C:\ArduinoIDE\arduino-1.8.8\libraries -libraries E:\electronics\arduino\libraries -fqbn=arduino:avr:mega:cpu=atmega2560 -ide-version=10808 -build-path C:\Users\per\AppData\Local\Temp\arduino_build_26620 -warnings=all -build-cache C:\Users\per\AppData\Local\Temp\arduino_cache_928852 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=C:\Users\per\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino4 -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino4.path=C:\Users\per\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino4 -prefs=runtime.tools.avrdude.path=C:\Users\per\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino14 -prefs=runtime.tools.avrdude-6.3.0-arduino14.path=C:\Users\per\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino14 -prefs=runtime.tools.arduinoOTA.path=C:\Users\per\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.2.0 -prefs=runtime.tools.arduinoOTA-1.2.0.path=C:\Users\per\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.2.0 -verbose C:\Users\per\AppData\Local\Temp\untitled692996215.tmp\sketch_dec28b\sketch_dec28b.ino

In this case, the temporary build folder is C:\Users\per\AppData\Local\Temp\arduino_build_26620. You will find the preprocessed sketch in the sketch subfolder of the build folder. It’s the .ino.cpp file. Open it in a text editor. The temporary build folder will be deleted when the Arduino IDE is closed.


cool thanks for the explanations - just what I was looking for...

yes IP is an array, but print(ip); works unexpectedly well.

well none of rs.setChannelData() functions work it seems, can you have a look within the library to see if you have they syntax correctly ? also shouldn't you declare the object globally rather then within setup() RemoteSign rs;  if you want to use it within loop() as well ?

well none of rs.setChannelData() functions work it seems, can you have a look within the library to see if you have they syntax correctly ? also shouldn't you declare the object globally rather then within setup() RemoteSign rs;  if you want to use it within loop() as well ?

I was not asking why the code was failing, I had to use code that fails to compile to ask why the compiler produces inaccurate line numbers.