6 KiB
title | description | guide_group | order |
---|---|---|---|
Common Syntax Errors | Details of common problems encountered when writing C apps for Pebble, and how to resolve them. | debugging | 2 |
If a developer is relatively new to writing Pebble apps (or new to the C language in general), there may be times when problems with an app's code will cause compilation errors. Some types of errors with the code itself can be detected by the compiler and this helps reduce the number that cause problems when the code is run on Pebble.
These are problems with how app code is written, as opposed to runtime errors (discussed in {% guide_link debugging/common-runtime-errors %}), which may include breaking the rules of the C language or bad practices that the compiler is able to detect and show as an error. The following are some examples.
Undeclared Variables
This error means that a variable that has been referenced is not available in the current scope.
../src/main.c: In function 'toggle_logging':
../src/main.c:33:6: error: 'is_now_logging' undeclared (first use in this function)
if(is_now_logging == true) {
^
In the above example, the symbol is_now_logging
has been used in the
toggle_logging
function, but it was not first declared there. This could be
because the declaring line has been deleted, or it was expected to be available
globally, but isn't.
To fix this, consider where else the symbol is required. If it is needed in
other functions, move the declaration to a global scope (outside any function).
If it is needed only for this function, declare it before the offending line
(here line 33
).
Undeclared Functions
Another variant of the above problem can occur when declaring new functions in a code file. Due to the nature of C compilation, any function a developer attempts to call must have been previously encountered by the compiler in order to be visible. This can be done through forward declaration.
For example, the code segment below will not compile:
static void window_load(Window *window) {
my_function();
}
void my_function() {
// Some code here
}
The compiler will report this with an 'implicit declaration' error, as the app has implied the function's existence by calling it, even though the compiler has not seen it previously:
../src/function-visibility.c: In function 'window_load':
../src/function-visibility.c:6:3: error: implicit declaration of function 'my_function' [-Werror=implicit-function-declaration]
my_function();
^
This is because the declaration of my_function()
occurs after it is called
in window_load()
. There are two options to fix this.
- Move the function declaration above any calls to it, so it has been encountered by the compiler:
void my_function() {
// Some code here
}
static void window_load(Window *window) {
my_function();
}
- Declare the function by prototype before it is called, and provide the implementation later:
void my_function();
static void window_load(Window *window) {
my_function();
}
void my_function() {
// Some code here
}
Too Few Arguments
When creating functions with argument lists, sometimes the requirements of the function change and the developer forgets to update the places where it is called.
../src/main.c: In function 'select_click_handler':
../src/main.c:57:3: error: too few arguments to function 'toggle_logging'
toggle_logging();
^
../src/main.c:32:13: note: declared here
static void toggle_logging(bool will_log) {
^
The example above reports that the app tried to call the toggle_logging()
function in select_click_handler()
on line 57, but did not supply enough
arguments. The argument list expected in the function definition is shown in the
second part of the output message, which here exists on line 32 and expects an
extra value of type bool
.
To fix this, establish which version of the function is required, and update either the calls or the declaration to match.
Incorrect Callback Implementations
In the Pebble SDK there are many instances where the developer must implement a
function signature required for callbacks, such as for a WindowHandlers
object. This means that when implementing the handler the developer-defined
callback must match the return type and argument list specified in the API
documentation.
For example, the WindowHandler
callback (used for the load
and unload
events in a Window
's lifecycle) has the following signature:
typedef void(* WindowHandler)(struct Window *window)
This specifies a return type of void
and a single argument: a pointer of type
Window
. Therefore the implemented callback should look like this:
void window_load(Window *window) {
}
If the developer does not specify the correct return type and argument list in their callback implementation, the compiler will let them know with an error like the following, stating that the type of function passed by the developer does not match that which is expected:
../src/main.c: In function 'init':
../src/main.c:82:5: error: initialization from incompatible pointer type [-Werror]
.load = main_window_load,
^
../src/main.c:82:5: error: (near initialization for '(anonymous).load') [-Werror]
To fix this, double check that the implementation provided has the same return type and argument list as specified in the API documentation.