I'm trying to run a example from the "Using Graphviz as a library" in http://www.graphviz.org/Documentation.php.
#include <gvc.h>
int main(int argc, char **argv)
{
Agraph_t *g;
Agnode_t *n, *m;
Agedge_t *e;
Agsym_t *a;
GVC_t *gvc;
/* set up a graphviz context */
gvc = gvContext();
/* parse command line args - minimally argv[0] sets layout engine */
gvParseArgs(gvc, argc, argv);
/* Create a simple digraph */
g = agopen("g", Agdirected);
n = agnode(g, "n", 1);
m = agnode(g, "m", 1);
e = agedge(g, n, m, 0, 1);
/* Set an attribute - in this case one that affects the visible rendering */
agsafeset(n, "color", "red", "");
/* Compute a layout using layout engine from command line args */
gvLayoutJobs(gvc, g);
/* Write the graph according to -T and -o options */
gvRenderJobs(gvc, g);
/* Free layout data */
gvFreeLayout(gvc, g);
/* Free graph structures */
agclose(g);
/* close output file, free context, and return number of errors */
return (gvFreeContext(gvc));
}
I'm compiling and linking with : gcc -Wall pkg-config libgvc --cflags --libs *.c -o EXE -lgvc
and then I see this result:
graph.c: In function ‘main’:
graph.c:14:18: error: ‘Agdirected’ undeclared (first use in this function)
graph.c:14:18: note: each undeclared identifier is reported only once for each function it appears in
graph.c:15:2: error: too many arguments to function ‘agnode’
In file included from /usr/include/graphviz/types.h:717:0,
from /usr/include/graphviz/gvc.h:20,
from graph.c:1:
/usr/include/graphviz/graph.h:185:22: note: declared here
graph.c:16:2: error: too many arguments to function ‘agnode’
In file included from /usr/include/graphviz/types.h:717:0,
from /usr/include/graphviz/gvc.h:20,
from graph.c:1:
/usr/include/graphviz/graph.h:185:22: note: declared here
graph.c:17:2: error: too many arguments to function ‘agedge’
In file included from /usr/include/graphviz/types.h:717:0,
from /usr/include/graphviz/gvc.h:20,
from graph.c:1:
/usr/include/graphviz/graph.h:192:22: note: declared here
graph.c:7:11: warning: unused variable ‘a’ [-Wunused-variable]
graph.c:6:12: warning: variable ‘e’ set but not used [-Wunused-but-set-variable]
Could anyone help me understand what is going on? Why the compiler is complaining about those arguments in those functions?
Thank you!!!!
I saved your code as g.c, then issued this command line
gcc -Wall `pkg-config libgvc --cflags --libs` g.c -o EXE -lgvc
that yields
g.c: In function ‘main’:
g.c:14:5: error: too few arguments to function ‘agopen’
/usr/local/include/graphviz/cgraph.h:266:18: note: declared here
g.c:7:14: warning: unused variable ‘a’ [-Wunused-variable]
g.c:6:15: warning: variable ‘e’ set but not used [-Wunused-but-set-variable]
then I added the miss parameter
g = agopen("g", Agdirected, 0);
and the miss library
gcc -Wall `pkg-config libgvc --cflags --libs` g.c -lgvc -lcgraph
now the code compile and link with just 2 warnings:
g.c: In function ‘main’:
g.c:7:14: warning: unused variable ‘a’ [-Wunused-variable]
g.c:6:15: warning: variable ‘e’ set but not used [-Wunused-but-set-variable]
I think it works because I've built graphviz from source, then pkg-config is up-to-date...
The program still need some debug, running it i get:
./a.out
There is no layout engine support for "a.out"
Use one of: circo dot fdp neato nop nop1 nop2 osage patchwork sfdp twopi
Error: Layout was not done. Missing layout plugins?
The message is because by default the layout engine use the exe name (i.e. a.out, default of gcc compile-and-link) as layout string...
Related
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
https://stackoverflow.com/questions/43423803/document-classification-tool-in-c-compilation-error/43432470#43432470
In above link-
I get 3 errors after adding -fnested_functions as
gcc -c ./rainbow.c -fnested-functions process_wv.c test_file.c test_hdb_file.c
(The 3 files process_wv, test_file, test_hdb_file are removed from rainbow.c and added as seperate .c files to the directory now)
Output:-
./bow/libbow.h:1345:8: note: forward declaration of 'struct argp_child'
struct argp_child; /* forward declare this type */
^
./rainbow.c:655:5: error: function definition is not allowed here
{
^
./rainbow.c:663:8: warning: extra tokens at end of #endif directive [-Wextra-tokens]
#endif VPC_ONLY
^
//
./rainbow.c:734:3: warning: implicit declaration of function 'do_indexing' is invalid in C99
[-Wimplicit-function-declaration]
do_indexing ();
^
./rainbow.c:1175:49: warning: passing 'int *' to parameter of type 'socklen_t *' (aka 'unsigned int *') converts between
pointers to integer types with different sign [-Wpointer-sign]
newsockfd = accept(rainbow_sockfd, &cli_addr, &clilen);
^~~~~~~
/usr/include/sys/socket.h:681:69: note: passing argument to parameter here
int accept(int, struct sockaddr * __restrict, socklen_t * __restrict)
^
./rainbow.c:1586:30: error: use of undeclared identifier 'test_file'
bow_map_filenames_from_dir (test_file.c, 0, dir, "");
^
P.S Why is test_file.c unidentified (bow_map_filenames_from_dir in docnames.c) in rainbow.c even though they are inside the same bow-20020213 folder (Permissions are 755 for all)
Regards
taking this .. as a starting point:
./bow/libbow.h:1345:8: note: forward declaration of 'struct argp_child'
struct argp_child; /* forward declare this type */
The linked code has a major problem in not including all the header files (in any specific header file) that that specific header file needs.
BTW: the 'struct argp_child' is defined in the ./argp/argp.h header file.
I did the following:
downloaded all the files via the .zip facility
expanded the .zip file to ~/src_bow on my ubuntu linux computer
cd ~/src_bow
./configure
edited the resulting 'Makefile' to define the macro:
CFLAGS = -g -O -Wall -Wextra -std=gnu11 -Wimplicit
then entered:
make -f Makefile
The result was hundreds of warnings, notes and errors
Most of the compiler output messages were about syntax, incomplete struct definitions, ignored modifiers and conversions However, there were many many other problems exposed.
After fixing a couple of hundred of the problems I stopped.
To answer your question, the root of the problems you are having has to do with the appropriate header files not being included in other header files that need the information in the header files that are not being included in each header file.
I am doing a C exercise that involves loading a shared library dynamically. When I compile my test program using gcc -o test2 test2.c -ldl command, I get an error:
test2.c: In function ‘main’:
test2.c:27:5: error: too many arguments to function ‘test’
(*test)(array, size);
This is the bit where I get the error:
void (*test)(void);
test = dlsym(handle, "lib_fill_random");
(*test)(array, size);
lib_fill_random is declared with two arguments in both in .h and .c files as void lib_fill_random(double *array, int size);, and it works perfectly fine by itself.
What could be causing this issue?
The function pointer declaration has to match the declaration of the actual function. So it should be:
void (*test)(double *, int);
Your declaration states that the function takes no arguments, so you get an error when you call it with arguments.
I define a structure that I call Neuron.
In my main, I create a two dimensional array:
Neuron N_network[4][10]; //create a neural network
I have a function to print the structure element:
void print_stat_neuron(Neuron * neuron_info)
What should I write to print N_network[i][j] (as an argument of the print_stat_neuron() function)?
I try simply with &(N_network[i][j]) and I get an error message.
I have the fallowing error message with the compiler gcc -Wall -Wextra:
2ex4.c: In function 'init_network':
2ex4.c:168:2: warning: implicit declaration of function'print_stat_neuron' [-Wimplicit-function-declaration]
print_stat_neuron(&N_network[4][1]);
^
2ex4.c: At top level:
2ex4.c:191:6: warning: conflicting types for 'print_stat_neuron' [enabled by default]
void print_stat_neuron(Neuron * neuron_info)
^
2ex4.c:168:2: note: previous implicit declaration of 'print_stat_neuron' was here
print_stat_neuron(&N_network[4][1]);
You need to change the parameter to Neuron (*neuron_info)[10]. Now you can call this function as
print_stat_neuron(N_network);
or
print_stat_neuron(&N_network[0]);
The error messages you show come from not declaring the function before using it, so the compiler deduces a type for the function (extern int print_stat_neuron(); with no specification for the number or types of the parameters), and then objects to you defining it with a return type of void. Note that in C, extern int print_stat_neuron(); is not a prototype for a function with no arguments; that's extern int print_stat_neuron(void);.
This code compiles cleanly:
typedef struct Neuron
{
int x;
} Neuron;
void print_stat_neuron(Neuron *neuron_info);
int main(void)
{
Neuron N_network[4][10];
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 10; j++)
print_stat_neuron(&N_network[i][j]);
}
return 0;
}
This declares the function before using it. It would also be acceptable to define the function before using it (which saves having a separate declaration). Of course, if the function will be used outside the source file where it is defined, it should have a declaration in a header, and the header should be used both where it is defined and where it is used. If the function is not used outside the source file where it is defined, it should be static.
Clean compilation checked with GCC 5.3.0 on Mac OS X 10.10.5 (my El Capitan machine is under warranty repair, unfortunately):
$ gcc -std=c11 -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
> -Wold-style-definition -c neuron.c
$
vi example.c
#include<stdio.h>
#include "flite.h"
register_cmu_us_kal();
int main(int argc,char** argv)
{
cst_voice *v;
if(argc!=2)
{
fprintf(stderr,"usage:file_test FILE\n");
exit(-1);
}
flite_init();
v=register_cmu_us_kal(NULL);
flite_file_to_speech(argv[1],v,"play");
return 0;
}
Compile:
desktop:
~/flite-1.4-release$ gcc example.c -I./include/ -L./build/i386-linux-gnu/lib -lflite -lflite_cmu_us_kal -lflite_cmulex -lflite_usenglish -lflite_cmu_us_rms -lflite_cmu_time_awb -lflite_cmu_us_slt -lflite_cmu_us_awb -lm -o example
example.c:3: warning: data definition has no type or storage class
example.c: In function ‘main’:
example.c:13: warning: assignment makes pointer from integer without a cast
I have explored the contents of the lib folder below.
desktop:
~/flite-1.4-release$ ls
ACKNOWLEDGEMENTS config.guess configure example flite.sln lang mkinstalldirs src wince
bin config.log configure.in example.c -I main palm testsuite windows
build config.status COPYING Exports.def include Makefile README test.txt
config config.sub doc fliteDll.vcproj install-sh missing sapi tools
desktop:
~/flite-1.4-release/build/i386-linux-gnu/lib$ ls
libflite.a libflite_cmu_us_awb.shared.a libflite_cmu_us_kal.so.1 libflite.shared.a
libflite_cmulex.a libflite_cmu_us_awb.so libflite_cmu_us_kal.so.1.4 libflite.so
libflite_cmulex.shared.a libflite_cmu_us_awb.so.1 libflite_cmu_us_rms.a libflite.so.1
libflite_cmulex.so libflite_cmu_us_awb.so.1.4 libflite_cmu_us_rms.shared.a libflite.so.1.4
libflite_cmulex.so.1 libflite_cmu_us_kal16.a libflite_cmu_us_rms.so libflite_usenglish.a
libflite_cmulex.so.1.4 libflite_cmu_us_kal16.shared.a libflite_cmu_us_rms.so.1 libflite_usenglish.shared.a
libflite_cmu_time_awb.a libflite_cmu_us_kal16.so libflite_cmu_us_rms.so.1.4 libflite_usenglish.so
libflite_cmu_time_awb.shared.a libflite_cmu_us_kal16.so.1 libflite_cmu_us_slt.a libflite_usenglish.so.1
libflite_cmu_time_awb.so libflite_cmu_us_kal16.so.1.4 libflite_cmu_us_slt.shared.a libflite_usenglish.so.1.4
libflite_cmu_time_awb.so.1 libflite_cmu_us_kal.a libflite_cmu_us_slt.so
libflite_cmu_time_awb.so.1.4 libflite_cmu_us_kal.shared.a libflite_cmu_us_slt.so.1
libflite_cmu_us_awb.a libflite_cmu_us_kal.so libflite_cmu_us_slt.so.1.4
Please help me to fix this problem.
The following declares a function that takes unspecified arguments and returns an int:
register_cmu_us_kal();
When you call it, you assign its result to a variable of type cst_voice*:
v=register_cmu_us_kal(NULL);
The compiler warns you about this conversion.
I think the best course of action is to provide a proper prototype for register_cmu_us_kal (perhaps by including the relevant header file).
You can fix this by changing your method declaration:
register_cmu_us_kal();
To
cst_voice *register_cmu_us_kal();
This tells the compiler that the method
register_cmu_us_kal(); returns a cst_voice * instead of an int which is the default, which, when you assign this:
v = register_cmu_us_kal(NULL);
First, you are calling the function with parameters where you define it without parameters, secondly it is warning you that you are trying to assign a int to a cst_voice *.