Skip to content

Non-void function with no values returned causes crash #5867

Closed
@garageeks

Description

@garageeks

Make your question, not a Statement, inclusive. Include all pertinent information:

What you are trying to do?
While writing firmware, I stumbled in puzzling crashes. This firmware used to work fine with arduino-esp32 2.0.0.
I reverted back to 1.0.6 and it worked. No compiler errors were thrown with both.
The crashes sometimes produced a Guru Meditation Error, sometimes it was stuck and the watchdog would trigger, sometimes it simply rebooted.
By reverting to the previous commit, and adding bit of new code at a time, I pinpointed the culprit.

An initialization function declared with a bool, had no returned values.
Latest print on Serial was "pin set" and then boom.

Looking closely, the firmware throws a warning:
[...] In function 'bool mcp23008Init()':
[...]:2570:1: warning: no return statement in function returning non-void [-Wreturn-type]
The line corresponds to the end of the mcp23008Init function.


setup () {
[...]

if(i2cScan(0,0x20)) {					//look for MCP23008 (bus 0, addr 20)
		mcp23008status = true;
		out.println(F("found"));

		mcp23008Init();
		mcp.digitalWrite(ioCameraPin, LOW);
		mcp.digitalWrite(ioHotspotPin, LOW);
		mcp.digitalWrite(ioBuzzerPin, LOW);
		mcp.digitalWrite(ioLoraPin, LOW);
		mcp.digitalWrite(ioSpotlightPin, LOW);
		mcp.digitalWrite(ioInverterPin, LOW);
		mcp.digitalWrite(ioLeftLedPin, LOW);
		mcp.digitalWrite(ioRightLedPin, LOW);
		out.println("Pin low");
	} else {
		out.println("MCP23008 not found!");
		blinkDelay = 1000;
		errorCode = setErrorBit(errorCode,3,1);			//3rd bit is mcp23008 error
	}	

[...]

}
bool mcp23008Init() {
	if(!mcp.begin(0x20,&Wire)) {
		errorCode = setErrorBit(errorCode,3,1);			//3nd bit is MCP23008 error
		out.println(F("MCP23008 init failed!"));
	} else {
		out.println("Initialized");
		errorCode = setErrorBit(errorCode,3,0);			//clear error
		mcp.pinMode(ioCameraPin, OUTPUT);
		mcp.pinMode(ioHotspotPin, OUTPUT);
		mcp.pinMode(ioBuzzerPin, OUTPUT);
		mcp.pinMode(ioLoraPin, OUTPUT);
		mcp.pinMode(ioSpotlightPin, OUTPUT);
		mcp.pinMode(ioInverterPin, OUTPUT);
		mcp.pinMode(ioLeftLedPin, OUTPUT);
		mcp.pinMode(ioRightLedPin, OUTPUT);
		out.println("Pin set");
	}
}

Hardware:

Board: ESP32 Dev Module
Core Installation version: 2.0.0 (crash), 1.0.6 (working)
IDE name: Platform.io
Flash Frequency: 40Mhz
PSRAM enabled: no
Upload Speed: 115200
Computer OS: Windows 10

According to some StackOverflow posts, declaring a non-void function without returning a result is undefined behavior. Probably some compiler settings changed between 1.0.6 and 2.0.0
https://stackoverflow.com/questions/57163022/c-crash-on-a-non-void-function-doesnt-have-return-statement

When changed the function to void, the code works with 2.0.0. as usual.

It is not a arduino-esp32 bug.
I would expect a compiler error, not a warning. However, if this is not possible, the noobs like me should be aware!

Activity

VojtechBartoska

VojtechBartoska commented on Apr 7, 2022

@VojtechBartoska
Contributor

Hello, we did some changes from v2.0.0. Are you able to validate this with version 2.0.3-RC1? Thanks!

garageeks

garageeks commented on Apr 8, 2022

@garageeks
Author

Hi, been using 2.0.1 so far with the proposed workaround (void function instead of non-void function).
I can give it a try with 2.0.3-RC1 and let you know

VojtechBartoska

VojtechBartoska commented on Apr 22, 2022

@VojtechBartoska
Contributor

@garageeks any updates?

WebDust21

WebDust21 commented on May 2, 2022

@WebDust21
Contributor

I've come across this exact same issue with the released 2.0.2. A project that compiled and ran just fine on 1.0.6...now bootloops the ESP32 on 2.0.2. Interestingly enough, the backtrace is reported corrupted every single time; I've never seen that before.

(Worth noting that the normal Arduino IDE compiler warnings are set to "None"; setting them to "Default" showed a lot of warnings.)

After several hours of debugging, I traced the issue down to a function declared "int func([args])", but which didn't have a RETURN on every single possible exit path. The corresponding warning provided was:
warning: control reaches end of non-void function [-Wreturn-type]

OK, whatever...updated compiler, new rules, it wasn't an error, etc. My code wasn't even looking at the return value in the first place--so it wasn't a code problem.

Only this is what was causing the ESP32 crash.
Apparently, if the function doesn't RETURN a value, the compiler for whatever unknown reason loops the function back on itself--to some random part of the function, anyway.

Debug PRINT statements show the following behavior in the function:

FuncStart, val: 0
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
Func Exit, no ret
_[ad infinitum]_

(where "Func Start" is at the top of the function, and "Func Exit" is at the end, right before the commented-out RETURN statement.) Yes, yes, I know, "what's the function do??" While that's not pertinent here, the function runs a Steinhart-Hart calculation and then prints it to an LCD (if requested, otherwise it returns the converted result without printing to the LCD).

Worth noting that the ESP32 doesn't crash when the Serial.Print statements are in place (due to the task scheduler getting a break). If I remove said statements (and leave the RETURN commented out), I get a crash dump like this:

E (17744) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (17744) task_wdt:  - IDLE (CPU 0)
E (17744) task_wdt: Tasks currently running:
E (17744) task_wdt: CPU 0: GUI
E (17744) task_wdt: CPU 1: IDLE
E (17744) task_wdt: Aborting.

abort() was called at PC 0x401081dc on core 0


Backtrace:0x400837a1:0x3ffbedbc |<-CORRUPTED




ELF file SHA256: 0000000000000000

Rebooting...

(worth noting, I did not edit the above dump at all; the "|<-CORRUPTED" is what the ESP32 sent)

It should be relatively trivial to make a very simple "reproduce case" for this.
But if the issue is the compiler having a bad day over a non-void function without a Return statement, then I would suggest that the compiler WARNING should be changed to an ERROR.

VojtechBartoska

VojtechBartoska commented on May 3, 2022

@VojtechBartoska
Contributor

hello, thanks for update. We will investigate this.

WebDust21

WebDust21 commented on May 3, 2022

@WebDust21
Contributor

I had to get the "latest" (2.0.3 ++ whatever!) Arduino-ESP32 firmware yesterday due to another bug that was fixed ~4 days ago (#6659 to be exact!), so if necessary, I can test this on the current "master" branch.

VojtechBartoska

VojtechBartoska commented on May 3, 2022

@VojtechBartoska
Contributor

@WebDust21 I don't understand all of those exclamation mark you have used... but we will soon release 2.0.3-stable so it can be retested with it.

hreintke

hreintke commented on May 7, 2022

@hreintke
Contributor

@WebDust21

OK, whatever...updated compiler, new rules, it wasn't an error, etc. My code wasn't even looking at the return value in the first place--so it wasn't a code problem

In C++, Omitting the return statement in a function which has a return type that is not void is undefined behavior.

It is a coding problem.

WebDust21

WebDust21 commented on May 7, 2022

@WebDust21
Contributor

@hreintke
I'm not saying that the "new behavior" in Arduino Core 2.x.x is incorrect by any means. Just that if this new behavior is going to be the de-facto method going forwards...that the compiler warning should be changed to a compiler error.

Especially considering that the default compiler alerts setting in Arduino IDE is "none."

WebDust21

WebDust21 commented on May 7, 2022

@WebDust21
Contributor

My point about saying "it wasn't a coding problem" was that my code was not faulting as a result of the undefined function response. The fault is a result of the compiler's handling of said function.

36 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Status: Needs investigationWe need to do some research before taking next steps on this issue

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

      Participants

      @martinbrennan@TD-er@hreintke@me-no-dev@WebDust21

      Issue actions

        Non-void function with no values returned causes crash · Issue #5867 · espressif/arduino-esp32