I maintain a very old C project (the programmer who wrote these is already long gone) and I found something like this:
(Lines beginning with //
give the name of the file that contains the following lines.)
// db/stor_procs/sp_table.c
/* Special hack prototype */
int32_t put_column_value(table_t * tab, row_t * row, u_int16_t colnum, rt_value_t * v);
// db/triggers/specials.c
/* BAD HACK */
int32_t put_column_value(table_t * tab, row_t * row, u_int16_t colnum, rt_value_t * v);
// db_sean_add_alarm/src/rt_access.c
int32_t put_column_value(struct xput_info *xptr, table_t * tab, row_t * row, u_int16_t colnum, rt_value_t * v);
// db_sean_add_alarm/stor_procs/sp_table.c
/* Special hack prototype */
int32_t put_column_value(table_t * tab, row_t * row, u_int16_t colnum, rt_value_t * v);
// db/src/rt_access.c
int32_t
put_column_value(struct xput_info *xptr, table_t * tab, row_t * row, u_int16_t colnum, rt_value_t * v){//....}
// db_sean_add_alarm/src/rt_access.c
int32_t
put_column_value(struct xput_info *xptr, table_t * tab, row_t * row, u_int16_t colnum, rt_value_t * v){//.....}
The programmer never declares put_column_value
in a header file, but only gives the definition in the .c files. The more curious thing is that I can't find any definition of put_column_value
that would take table_t *
as the first parameter, and I'm 100% sure that table_t
and struct xput_info
are different types (structures).
But that's not the whole story. The weirdest part is that I can find declarations of put_column_value
in other .c files. Now I need to clean up the code, but I cannot understand how to deal with this kind of C magic. What is the "magic" (hack) the original programmer used here?
The whole project is kind of big, and I've already tried my best to simplify the problem. Please tell me if there's any additional information you need to solve this problem.
Edit
Find out why, this project link to the other library, and that library has a definition of the function prototype, that is why this "magic"(hack) can find the implementation. Now come a big problem to solve--this project do not have solid unit test and hard to develop one for it, without testing I cannot change the codes, without changing the codes I cannot do unit test ^_^. Ahhh, maintain legacy codes always is not a pleasant task.
A function declaration tells the compiler about a function's name, return type, and parameters. A function definition provides the actual body of the function. The C standard library provides numerous built-in functions that your program can call.
Function declaration is a prototype that specifies the function name, return types and parameters without the function body. Function Definition, on the other hand, refers to the actual function that specifies the function name, return types and parameters with the function body.
i.e., declaration gives details about the properties of a variable. Whereas, Definition of a variable says where the variable gets stored. i.e., memory for the variable is allocated during the definition of the variable. In C language definition and declaration for a variable takes place at the same time.
A function declaration introduces an identifier that designates a function and, optionally, specifies the types of the function parameters (the prototype). Function declarations (unlike definitions) may appear at block scope as well as file scope.
You have several things to worry about here.
So the first part you are confused about is the mismatch between declarations and definitions.
For the build process, that's ok as long as no compilation unit sees them both. But the program doesn't work at this place, does it?
The second part, which is about putting declarations into other .c files, is very bad style. It should - if at all - only be used during debugging where I temporarily need a function in another file.
You can fix both by putting the (correct) declaration into a header file which you include from where you need it as well as - in order to detect mismatches - from where you declare it.
OUCH! My guess is that the prior programmer needed to add a parameter to put_column_value
in one place, but was too lazy to do it everywhere. It is also possible that he was halfway through the implementation and meant to fix the other files, but then quit before the job was finished.
You should look at the linker command(s) to see which definition is actually linked with the program(s).
You should also check to see if put_column_value
is ever called (at runtime) from the files that have the faulty declaration. Since the extra parameter is placed first, calls using the faulty declaration could still work as long as the implementation doesn't actually use the new parameter in those instances (if it writes to it, it will corrupt the stack). Hence "Magic hack". It breaks the C standard and technically results in undefined behaviour.
My advice is that you either fix the call everywhere or that you spit the function into two, and rename one of them. In either case, you should move the declaration(s) back to the header file.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With