I am trying to build a wireless driver which is eventually failing on an implicit declaration error:
wl_iw.c: In function 'wl_iw_set_priv':
wl_iw.c:7649:4: error: implicit declaration of function 'wl_iw_set_cscan' [-Werror=implicit-function-declaration]
Here is where it tries to call the function:
#if defined(CSCAN)
else if (strnicmp(extra, CSCAN_COMMAND, strlen(CSCAN_COMMAND)) == 0)
ret = wl_iw_set_cscan(dev, info, (union iwreq_data *)dwrq, extra);
#endif
So, it seems like this will only be called if CSCAN is defined. Well, in the source file, wl_iw_set_cscan is also declared if CSCAN is declared (I believe). Here is where it is defined (github), and... if you scroll up a little bit, it only seems to be dependent on CSCAN being defined.
CSCAN is definitely defined, which is shown if I do a verbose build:
arm-linux-androideabi-gcc *snip* -DCSCAN *snip* -c -o /home/owner/android-wmon/core/compat-wireless-3.6-rc7-1/drivers/net/wireless/bcmdhd/wl_iw.o /home/owner/android-wmon/core/compat-wireless-3.6-rc7-1/drivers/net/wireless/bcmdhd/wl_iw.c
I can even be doubly sure by putting a "#define CSCAN" at the top of wl_iw.c and it will complain that it is defined twice. So I'm positive that CSCAN is defined.
If this is the case, why am I getting an implicit definition warning turned error? wl_iw_set_cscan should be defined since CSCAN is defined.
At line 5781, there is another #define that is masking wl_iw_set_cscan.
Related
In C it is an idiomatic pattern to have your .h file contain declarations of the externally visible symbols in the corresponding .c file. The purpose if this is to support a kind of "module & interface" thinking, e.g enabling a cleaner structure.
In a big legacy C system I'm working on it is not uncommon that functions are declared in the wrong header files probably after moving a function to another module, since it still compiles, links and runs, but that makes the modules less explicit in their interfaces and indicates wrong dependencies.
Is there a way to verify / confirm / guarantee that the .h file has all the external symbols from .c and no external symbols that are not there?
E.g. if I have the following files
module.c
int func1(void) {}
bool func2(int c) {}
static int func3(void) {}
module.h
extern int func1(void);
extern bool func4(char *v);
I want to be pointed to the fact that func4 is not an external visible symbol in module.c and that func2 is missing.
Modern compilers give some assistance in as so much that they can detect a missing declaration that you actually referenced, but it does not care from which file it comes.
What are my options, other than going over each pair manually, to obtain this information?
I want to be pointed to the fact that func4 is not an external visible symbol in module.c and that func2 is missing.
Using POSIX-ish linux with bash, diff and ctags and given really simple example of input files, you could do this:
$ #recreate input
$ cat <<EOF >module.c
int func1(void) {}
bool func2(int c) {}
static int func3(void) {}
EOF
$ cat <<EOF >module.h
extern int func1(void);
extern bool func4(char *v);
EOF
$ # helper function for extracting only non-static function declarations
$ f() { ctags -x --c-kinds=fp "$#" | grep -v static | cut -d' ' -f1; }
$ # simply a diff
$ diff <(f module.c) <(f module.h)
2,3c2
< func2
---
> func4
$ diff <(f module.c) <(f module.h) |
> grep '^<\|^>' |
> sed -E 's/> (.*)/I would like to point the fact that \1 is not externally visible symbol/; s/< (.*)/\1 is missing/'
func2 is missing
I would like to point the fact that func4 is not externally visible symbol
This will break if for example static keyword is not on the same line as function identifier is introduced, because ctags will not output it them. So the real job of this is getting the list of externally visible function declarations. This is not an easy task and writing such tool is left to others : )
It does not make any sense as if you call not defined function, the linker will complain.
More important is to have all functions prototypes - as compiler has to know how to call them. But in this case compilers emit warnings.
Some notes: you do not need the keyword extern as functions are extern by default.
This is the time to shine for some of my favorite compiler warning flags:
CFLAGS += -Wmissing-prototypes \
-Wstring-prototypes \
-Wmissing-declarations \
-Wold-style-declaration \
-Wold-style-definition \
-Wredundant-decls
This at least ensures, that all the source files containing implementations of a function that is not static also have a previous external declaration & prototype of said function, ie. in your example:
module.c:4:6: warning: no previous prototype for ‘func2’ [-Wmissing-prototypes]
4 | bool func2(int c) { return c == 0; }
| ^~~~~
If we'd provide just a forward declaration that doesn't constitute a full prototype we'd still get:
In file included from module.c:1:
module.h:7:1: warning: function declaration isn’t a prototype [-Wstrict-prototypes]
7 | extern bool func2();
| ^~~~~~
module.c:4:6: warning: no previous prototype for ‘func2’ [-Wmissing-prototypes]
4 | bool func2(int c) { return c == 0;}
| ^~~~~
Only providing a full prototype will fix that warning. However, there's no way to make sure that all declared functions are actually also implemented. One could go about this using linker module definition files, a script using nm(1) or a simple "example" or unit test program, that includes every header file and tries to call all functions.
To list the differences between the exported symbols in a .c module in C and the corresponding .h file you can use chcheck. Just give the module name on the command line
python3 chcheck.py <module>
and it will list what externally visible functions are defined in the .c module but not exposed in the .h header file, and if there are any functions in the header module that are not defined in the corresponding .c file.
It only checks for function declarations/definitions at this point.
Disclaimer I wrote this to solve my own problem. Its built in Python on top of #eliben:s excellent pycparser.
Output for the example in the question is
Externally visible definitions in 'module.c' that are not in 'module.h':
func2
Declarations in 'module.h' that have no externally visible definition in 'module.c':
func4
I have some example code. When I uncomment the invalid_call function call I get a compiler error as expected. Unfortunately, calling my_function with wrong number of arguments still compiles leading to undefined behavior (UB).
main.c
#include <linux/module.h>
#include <linux/kernel.h>
#include "header.h"
extern void my_function(int x);
static int my_init(void)
{
my_function(5);
// invalid_call( 5 ); // doesn't compile
return 0;
}
static void my_exit(void)
{
pr_info("removing module");
}
module_init(my_init);
module_exit(my_exit);
func_source.c
#include <linux/kernel.h>
void my_function(int x, int y)
{
pr_info("%d %d",x,y);
}
header.h
void invalid_call(int x, int y)
{
return;
}
Expected output:
Compiler error when calling my_function() with only one argument.
Actual output:
Code compiles and prints a random value for y, essentially UB.
I know that extern void my_function(int x); is just another declaration so I don't think compiler needs to throw an error however, when I call my_function with a single argument, it shouldn't be able to find a match to any function definition. Unfortunately, instead of a compiler error I run into UB.
How does this work? I know UB is UB but how why does it become UB. I thought the function signature mismatch would cause a compiler. My suspicion is the extern declaration but still...
Also, bonus question. How do I avoid running into this problem again? Any design patterns or practices I can follow?
Here is the Makefile if you want to test it out yourself.
obj-m += main.o
example-y := ./src/main.o ./src/func_src.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Folder structure:
./Makefile
./src/main.c
./src/my_func.c
Thanks in advance.
In C, at least, neither the compiler nor the linker has global knowledge of all the functions in all the source files of your program (or kernel module, or whatever). The compiler compiles one source file at a time, and all it has to go on is the declarations -- including the prototypes -- that are visible during that one compilation. So if the prototype is wrong -- you're doomed. The compiler validates your (incorrect) call against the (incorrect) prototype, and finds no mismatch, and so generates an (incorrect) call that passes one argument, leading to the behavior you see.
For this reason it's an excellent idea to:
never put external prototypes in .c files, but rather, in .h files, which you include wherever you call the functions, and
also include the .h file in the source file where you define the function.
That way, not only does the compiler check that the calls match the prototype, it can also check that the prototype matches the actual definition, and since there's only one copy of the prototype (in that one .h file), it's more or less impossible for it to fall out of sync and end up being incorrect. See also this question.
In your question, you seemed to think that it wouldn't even be possible for the incorrect call to be linked up with the two-argument-accepting definition. That might be true in C++, where "name mangling" arranges for a function's arguments to be part of its signature. But nothing like that happens in C. Your function's sole identity -- in the symbol table, and as far as the linker is concerned -- is the name my_function, and nothing at link time prevents a one-arg-passing call from being matched up with the two-arg-accepting definition.
Some ways to detect this problem:
building in gcc with link-time optimization will usually flag this.
Using -Wmissing-prototypes would have warned for func_source.c that you have an externally-visible function with no prototype.
You should have the correct prototype in a header file that is included by all units that want to call the function, as well as the unit containing the function definition. The latter warning flag will detect if you forget to put the prototype in the unit containing the definition (which would have caused a compilation error due to the prototype not matching the definition).
the OPs posted code results in the following messages from the compiler:
gcc -ggdb -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled.c" (in directory: /home/richard/Documents/forum)
untitled.c: In function ‘invalid_call’:
untitled.c:1:23: warning: unused parameter ‘x’ [-Wunused-parameter]
void invalid_call(int x, int y)
^
untitled.c:1:30: warning: unused parameter ‘y’ [-Wunused-parameter]
void invalid_call(int x, int y)
^
untitled.c: In function ‘my_init’:
untitled.c:15:5: warning: implicit declaration of function ‘my_function’; did you mean ‘myFunction’? [-Wimplicit-function-declaration]
my_function(5);
^~~~~~~~~~~
myFunction
untitled.c: In function ‘my_exit’:
untitled.c:22:5: warning: implicit declaration of function ‘pr_info’ [-Wimplicit-function-declaration]
pr_info("removing module");
^~~~~~~
untitled.c: At top level:
untitled.c:25:1: warning: data definition has no type or storage class
module_init(my_init);
^~~~~~~~~~~
untitled.c:25:1: warning: type defaults to ‘int’ in declaration of ‘module_init’ [-Wimplicit-int]
untitled.c:25:1: warning: parameter names (without types) in function declaration
untitled.c:26:1: warning: data definition has no type or storage class
module_exit(my_exit);
^~~~~~~~~~~
untitled.c:26:1: warning: type defaults to ‘int’ in declaration of ‘module_exit’ [-Wimplicit-int]
untitled.c:26:1: warning: parameter names (without types) in function declaration
untitled.c:28:6: warning: conflicting types for ‘my_function’
void my_function(int x, int y)
^~~~~~~~~~~
untitled.c:15:5: note: previous implicit declaration of ‘my_function’ was here
my_function(5);
^~~~~~~~~~~
untitled.c:20:13: warning: ‘my_exit’ defined but not used [-Wunused-function]
static void my_exit(void)
^~~~~~~
untitled.c:13:12: warning: ‘my_init’ defined but not used [-Wunused-function]
static int my_init(void)
^~~~~~~
Compilation finished successfully.
Suggest enabling the warnings when compiling, then fix those warnings
This question already has answers here:
What is the difference between a definition and a declaration?
(27 answers)
Closed 5 years ago.
I have two .c files, one of them has the definition of x, and the other file is using x, as follows:
file1.c:
int x;
//other code...
main.c:
int main(void)
{
printf("%d", x);
}
Now, when I compile this code, I get the following compilation error message:
In function 'main':
error: 'x' undeclared (first use in this function)
So, if a global variable (in this case x) is 'extern' by default, then why can't main.c file see x?
When I now go to main.c and define x, so that main.c now looks like:
int x=9; //This line was added.
int main(void)
{
printf("%d",x);
}
And also initialize x in file1.c, the program doesn't compile and I get the following error message:
error: ld returned 1 exit status
So, if main.c can't see x that is in file1.c, then this time what is the problem?
Is this a linking error?
Note that when I add
extern int x;
in main.c, the problem disappears.
Each compilation unit (in this case your individual .c files) is compiled separately. The compiler needs to know the storage class of x in order to handle it, so your first error (undeclared) comes from the compiler not knowing what x is. The compiler does not need to know where x lives.
When you then link your compiled objects together, the linker resolves any external names (including x in main.c if you've marked it extern) and the final executable will then have all its variables in known places. If it finds 2 extern symbols with the same name, then it will fail, giving you your second error (error: ld returned 1 exit status).
You must declare you variable in main.c, so the compiler knows about it: extern int x. The compiler said it to you: error: 'x' undeclared
You added the second definition of x in main.c, the first definition you did in file1.c. The linker informed you about ambiguity between two definitions. You could read the error above the line error: ld returned 1 exit status
I am building cairo from source using Clang. I get the following error:
src/cairo-quartz-font.c:368:1: error: conflicting types for 'cairo_quartz_font_face_create_for_cgfont'
cairo_quartz_font_face_create_for_cgfont (CGFontRef font)
^
src/cairo-quartz-font.c:247:18: note: previous implicit declaration is here
*font_face = cairo_quartz_font_face_create_for_cgfont (cgFont);
However, looking at the source, I find these definitions:
247:
CGFontRef cgFont = NULL;
// ...
*font_face = cairo_quartz_font_face_create_for_cgfont (cgFont);
CGFontRelease (cgFont);
368:
cairo_font_face_t *
cairo_quartz_font_face_create_for_cgfont (CGFontRef font)
{
cairo_quartz_font_face_t *font_face;
// ...
The full source is mirrored here.
What is the type conflict here?
When you use the function cairo_quartz_font_face_create_for_cgfont at line 247, it is undeclared (you should get a warning about that unless you fail to use -Wall). So the compiler fills in an assumed return type of int.
When you finally declare the function, its return type is not int. So that's a type conflict.
Normally this sort of problem would be avoided by #includeing a header with the function prototypes.
Just a simple program, but I keep getting this compiler error. I'm using MinGW for the compiler.
Here's the header file, point.h:
//type for a Cartesian point
typedef struct {
double x;
double y;
} Point;
Point create(double x, double y);
Point midpoint(Point p, Point q);
And here's point.c:
//This is the implementation of the point type
#include "point.h"
int main() {
return 0;
}
Point create(double x, double y) {
Point p;
p.x = x;
p.y = y;
return p;
}
Point midpoint(Point p, Point q) {
Point mid;
mid.x = (p.x + q.x) / 2;
mid.y = (p.y + q.y) / 2;
return mid;
}
And here's where the compiler issue comes in. I keep getting:
testpoint.c: undefined reference to 'create(double x, double y)'
While it is defined in point.c.
This is a separate file called testpoint.c:
#include "point.h"
#include <assert.h>
#include <stdio.h>
int main() {
double x = 1;
double y = 1;
Point p = create(x, y);
assert(p.x == 1);
return 0;
}
I'm at a loss as to what the issue could be.
How are you doing the compiling and linking? You'll need to specify both files, something like:
gcc testpoint.c point.c
...so that it knows to link the functions from both together. With the code as it's written right now, however, you'll then run into the opposite problem: multiple definitions of main. You'll need/want to eliminate one (undoubtedly the one in point.c).
In a larger program, you typically compile and link separately to avoid re-compiling anything that hasn't changed. You normally specify what needs to be done via a makefile, and use make to do the work. In this case you'd have something like this:
OBJS=testpoint.o point.o
testpoint.exe: $(OBJS)
gcc $(OJBS)
The first is just a macro for the names of the object files. You get it expanded with $(OBJS). The second is a rule to tell make 1) that the executable depends on the object files, and 2) telling it how to create the executable when/if it's out of date compared to an object file.
Most versions of make (including the one in MinGW I'm pretty sure) have a built-in "implicit rule" to tell them how to create an object file from a C source file. It normally looks roughly like this:
.c.o:
$(CC) -c $(CFLAGS) $<
This assumes the name of the C compiler is in a macro named CC (implicitly defined like CC=gcc) and allows you to specify any flags you care about in a macro named CFLAGS (e.g., CFLAGS=-O3 to turn on optimization) and $< is a special macro that expands to the name of the source file.
You typically store this in a file named Makefile, and to build your program, you just type make at the command line. It implicitly looks for a file named Makefile, and runs whatever rules it contains.
The good point of this is that make automatically looks at the timestamps on the files, so it will only re-compile the files that have changed since the last time you compiled them (i.e., files where the ".c" file has a more recent time-stamp than the matching ".o" file).
Also note that 1) there are lots of variations in how to use make when it comes to large projects, and 2) there are also lots of alternatives to make. I've only hit on the bare minimum of high points here.
I had this issue recently. In my case, I had my IDE set to choose which compiler (C or C++) to use on each file according to its extension, and I was trying to call a C function (i.e. from a .c file) from C++ code.
The .h file for the C function wasn't wrapped in this sort of guard:
#ifdef __cplusplus
extern "C" {
#endif
// all of your legacy C code here
#ifdef __cplusplus
}
#endif
I could've added that, but I didn't want to modify it, so I just included it in my C++ file like so:
extern "C" {
#include "legacy_C_header.h"
}
(Hat tip to UncaAlby for his clear explanation of the effect of extern "C".)
I think the problem is that when you're trying to compile testpoint.c, it includes point.h but it doesn't know about point.c. Since point.c has the definition for create, not having point.c will cause the compilation to fail.
I'm not familiar with MinGW, but you need to tell the compiler to look for point.c. For example with gcc you might do this:
gcc point.c testpoint.c
As others have pointed out, you also need to remove one of your main functions, since you can only have one.
Add the "extern" keyword to the function definitions in point.h
I saw here that this question
In c programming language, i keep getting this error
has been answered here so the thread seems closed for answers.
I disagree. It is different code.
The answer should be that we don't know what is in custom header file "functions.h".
Also, we don't know what are
MAPA m;
POSICAO heroi;
Are these functions, constants?
If these were some constants, one should expect #define in front of them, and no semicolon e.g.
#define MAPA m
#define POSICAO heroi
If You intended to prototype the function, since there's is semicolon behing, than You did not insert the parentheses ().
In that case MAPA and POSICAO are some custom-type functions, whose content should be determined in "Functions.h"
Also, there's a possibilty that You wanted to import the functions or variable or constant from some other directory, and in that case You're missing the word
extern MAPA m;
I had a similar problem running a bunch of .c files in a directory all linking to one header file with custom function prototypes.
I ran:
$gcc -Wall -Werror -Wextra -pedantic -std=gnu89 *.c
Getting these errors:
/usr/bin/ld: /tmp/ccovH4zH.o: in function `_puts': 3-puts.c:(.text+0x2f): undefined reference to `_putchar'
/usr/bin/ld: 3-puts.c:(.text+0x51): undefined reference to `_putchar'
/usr/bin/ld: /tmp/ccGeWRqI.o: in function `main': _putchar.c:(.text+0xe): undefined reference to `_putchar'
/usr/bin/ld: _putchar.c:(.text+0x18): undefined reference to `_putchar'
/usr/bin/ld: _putchar.c:(.text+0x22): undefined reference to `_putchar'
/usr/bin/ld: /tmp/ccGeWRqI.o:_putchar.c:(.text+0x2c): more undefined references to `_putchar' follow
collect2: error: ld returned 1 exit status
Note: All files were linked to the same header file with all the function declarations.
I manage to compile successfully after adding -c option to the gcc compiler like:
$gcc -Wall -Werror -Wextra -pedantic -std=gnu89 -c *.c
This run successfully.
Just in case anyone comes across the same.