C compiles with an undefined symbol - c

I am using an older version of the Diab C compiler.
In my code I have taken a function name and redefined it as a function pointer with the same signature. Before making this change the code worked. After the change it made it caused the embedded system to lock up.
The function pointer was declared extern in a header, defined in one .c file, and used in another .c file. When it was called from the second .c file it would cause the system to lock up. When I attempted to add debug information using sprintf it finally told me that it was an undefined symbol. I realized that the header file was was not included in the second .c file. When I #included it everything compiled and worked correctly.
My question is, is there some C rule that allowed the compiler to deduce the function signature even though the symbol was undefined at the call location? To my understanding there should have been an error long before I made any changes.

If no declaration is available, the compiler uses a default declaration of a function taking an unknown number of arguments and returning an int. If you turn up compiler warnings (eg -Wall -Wextra -Werror with gcc, check the documentation for your compiler), you should get a compile time warning.

Most likely, the code at first worked because it was compiled in the C89 or similar mode. The C standard from 1989 allows calling functions without first declaring them.
When you changed the code to use a pointer but didn't include the declaration of the pointer, the compiler assumed that your pointer was in fact a function and generated code to call into the pointer, as if the pointer had executable code inside. As the result, the program understandably stopped working.
What you should do is enable all possible warnings (for gcc: -Wall, -Wextra and make sure optimization is enabled (-O2 is good) because it enables code analysis), especially for calling functions without prototypes. A better thing might be to switch the compiler into the C99 mode (-std=c99 in gcc) or switch to a C99 compiler. The C standard from 1999 prohibits calling functions without prototypes and comes with some useful features absent in C89.

Related

Resolve undefined reference by stripping unused code

Assume we have the following C code:
void undefined_reference(void);
void bad(void) {
undefined_reference();
}
int main(void) {}
In function bad we fall into the linker error undefined reference to 'undefined_reference', as expected. This function is not actually used anywhere in the code, though, and as such, for the execution of the program, this undefined reference doesn't matter.
Is it possible to compile this code successfully, such that bad simply gets removed as it is never called (similar to tree-shaking in JavaScript)?
This function is not actually used anywhere in the code!
You know that, I know that, but the compiler doesn't. It deals with one translation unit at a time. It cannot divine out that there are no other translation units.
But main doesn't call anything, so there cannot be other translation units!
There can be code that runs before and after main (in an implementation-defined manner).
OK what about the linker? It sees the whole program!
Not really. Code can be loaded dynamically at run time (also by code that the linker cannot see).
So neither the compiler nor linker even try to find unused function by default.
On some systems it is possible to instruct the compiler and the linker to try and garbage-collect unused code (and assume a whole-program view when doing so), but this is not usually the default mode of operation.
With gcc and gnu ld, you can use these options:
gcc -ffunction-sections -Wl,--gc-sections main.c -o main
Other systems may have different ways of doing this.
Many compilers (for example gcc) will compile and link it correctly if you
Enable optimizations
make function bad static. Otherwise, it will have external linkage.
https://godbolt.org/z/KrvfrYYdn
Another way is to add the stump version of this function (and pragma displaying warning)

Why does calling system() without including stdlib.h still work?

The only library I've included in my C program is stdio.h. Calling system() within that very same program works anyway, though Eclipse complains about an implicit declaration of function ‘system’ [-Wimplicit-function-declaration], whatever that means.
However, GCC (the compiler I'm using) seems happy. Would it be that Eclipse is automatically fixing the issue before compilation, or is GCC just kind enough to do that without complaining? I understand nothing of this.
I'm using GNU/Linux Debian 11 (Bullseye) Stable, if that makes any difference.
Once upon a time, the rule in C was that if you called a function the compiler had never heard of, it quietly assumed it was an ordinary function returning int.
The system() function fits that description.
In more recent versions of the C Standard, the "implicit int" rule has been removed, and you are required to declare all functions before calling them. A modern compiler is obliged to issue a diagnostic if you fail to declare a called function. However, there's nothing keeping the compiler from having the diagnostic be a nonfatal warning, and going on to compile your program anyway, making use of the old assumption. And in fact, many compilers still do that, perhaps to make it easier to compile old code written under the old rules.

GCC how to stop false positive warning implicit-function-declaration for functions in ROM?

I want to get rid of all implicit-function-declaration warnings in my codebase. But there is a problem because some functions are
programmed into the microcontroller ROM at the factory and during linking a linker script provides only the function address. These functions are called by code in the SDK.
During compilation gcc of course emits the warning implicit-function-declaration. How can I get rid of this warning?
To be clear I understand why the warning is there and what does it mean. But in this particular case the developers of SDK guarantee that the code will work with implicit rules (i.e. implicit function takes only ints and returns an int). So this warning is a false positive.
This is gnu-C-99 only, no c++.
Ideas:
Guess the argument types, write a prototype in a header and include that?
Tell gcc to treat such functions as false positive with some gcc attribute?
You can either create a prototype function in a header, or suppress the warnings with the following:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
/* line where GCC complains about implicit function declaration */
#pragma GCC diagnostic pop
Write a small program that generates a header file romfunctions.h from the linker script, with a line like this
int rom_function();
for each symbol defined by the ROM. Run this program from your Makefiles. Change all of the files that use these functions to include romfunctions.h. This way, if the linker script changes, you don't have to update the header file by hand.
Because most of my programming expertise was acquired by self-study, I intentionally have become somewhat anal about resolving non-fatal warnings, specifically to avoid picking up bad coding habits. But, this has revealed to me that such bad coding habits are quite common, even from formally trained programmers. In particular, for someone like me who is also anal about NOT using MS Windows, my self-study of so-called platform-independent code such as OpenGL and Vulkan has revealed a WORLD of bad coding habits, particularly as I examine code written assuming the student was using Visual Studio and a Windows C/C++ compiler.
Recently, I encountered NUMEROUS non-fatal warnings as I designed an Ubuntu Qt Console implementation of an online example of how to use SPIR-V shaders with OpenGL. I finally threw in the towel and added the following lines to my qmake .PRO file to get rid of the non-fatal-warnings (after, first, studying each one and convincing myself it could be safely ignored) :
QMAKE_CFLAGS += -Wno-implicit-function-declaration
-Wno-address-of-packed-member
[Completely written due to commends]
You are compiling the vendor SDK with your own code. This is not typically what you want to do.
What you do is you build their SDK files with gcc -c -Wno-implicit-function-declaration and and your own files with gcc -c or possibly gcc -o output all-your-c-files all-their-o-files.
C does not require that declarations be prototypes, so you can get rid of the problem (which should be a hard error, not a warning, since implicit declarations are not valid C) by using a non-prototype declaration, which requires only knowing the return type. For example:
int foo();
Since "implicit declarations" were historically treated as returning int, you can simply use int for all of them.
If you are using C program, use
#include <stdio.h>

Detection of unused function and code in C

Iam writing a program in C. Is there any way(gcc options) to identify the unused code and functions during compilation time.
If you use -Wunused-function, you will get warnings about unused functions. (Note that this is also enabled when you use -Wall).
See http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html for more details.
gcc -Wall will warn you about unused static functions and some other types of unreachable code. It will not warn about unused functions with external linkage, though, since that would make it impossible to write a library.
No, there is no way to do this at compile time. All the compiler does is create object code - it does not know about external code that may or may not call functions you write. Have you ever written a program that calls main? It is the linker that determines if a function (specifically, a symbol) is used in the application. And I think GCC will remove unused symbols by default.

Why am I able to compile and run C programs without including header files?

I have tested this fact on Turbo C++ 3.0, VC++ 2008 express and Borland C++ 6.
If I add a C program with *.C extension to the project, I am able to compile and run the program without including header files. But in this case, some functions (like sqrt(), etc..) are returning erroneous values.
If I add a C program with *.CPP extension to the project, I am not able to compile and run the program without including header files.
Why?
In C, when the compiler does not find the definition of a function, it assumes it's an external function returning an integer. So the code compiles, and if the linker then finds a function with corresponding name it will run as well. But possibly with unexpected results.
By default in C function return type is int, and even if prototype not declared you'll be able to use, for example, libc functions. Of course, if its return value not int, you've got erroneous values.
C++ are more stricter and disallow this.
Also, gcc implements some functions as built-ins. You can try compiling with -fno-builtin options, if you use it.
If you don't provide a declaration for a function, C makes a guess at it. This guess is almost always wrong, hence your "erroneous values". C++ doesn't do this.
The C++ standard requires a function prototype to be seen before a function is used.
C does not have this requirement. If a C compiler sees an undeclared function it creates an implicit declaration assuming that the function returns int. If the function doesn't really return int unpredictable things will happen, as you are seeing with sqrt.

Resources