Strange declaration and function definition in C

I support a very old C project (the programmer who wrote them has long been gone) and I found something like this:

(Lines starting with // give the name of the file containing the following lines.)

Ads:

 // 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); 

Definition:

 // 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 the header file, but gives only the definition in the .c files. More curiously, I cannot find any definition of put_column_value that would take table_t * as the first parameter, and I am 100% sure that table_t and struct xput_info are different types (structures).

But that is not the whole story. The weird thing is that I can find put_column_value in other .c files. Now I need to clear the code, but I can’t figure out how to deal with this type C. What is the “magic” (hacking) of the original programmer used here?

The whole project is quite large, and I already tried my best to simplify this problem. Please tell me if there is any additional information necessary to solve this problem.

Edit

Find out why this project refers to another library, and this library has a function prototype definition, so this “magic” (hack) can find an implementation. Now the big problem has come to solve - this project does not have a solid unit test and it is difficult to develop for it, without testing I can’t change the codes without changing the codes, I can’t do the unit test ^ _ ^. Ahhh, maintaining legacy codes is not always a pleasant task.

+5
source share
3 answers

You have a few things to worry about.

  • A terrible programming style that puts prototypes in source code, not header files. This is easy (but tedious) to fix.
  • Inconsistency between declarations and definitions. Given that the prototype has several parameters, as well as two function definitions. It seems likely that these prototypes are not actually used, because if they were a program, it would have crashed (assuming that the actual code is not doing something really disgusting with its arguments). Thus, you may be able to do some cleanup.
  • You have two put_column_value implementations. Presumably, they are in what should be in different libraries that should never be used together. It looks like one of these directories contains a new version of the library with some kind of signal, but I just guess from the name.
+4
source

So, the first part that you confuse is the discrepancy between declarations and definitions.

This is normal for the build process until the compilation unit sees both of them. But the program does not work in this place, right?

The second part regarding the placement of ads in other .c files is very bad. It should - if at all - be used only during debugging, when I temporarily need a function in another file.

You can fix this by placing the (correct) ad in the header file that you include, where it comes from, and also - to detect inconsistencies - where you declare it from.

+3
source

OH! I assume that the previous programmer needed to add the put_column_value parameter in one place, but was too lazy to do this everywhere. It is also possible that he was halfway to the implementation and intended to fix other files, but then stopped working until the work was completed.

You should look at the linker command (s) to find out which definition is really associated with the program (s).

You should also check if put_column_value (at run time) is called from files with an erroneous declaration. Since the optional parameter is placed first, calls using the erroneous declaration may still work until the implementation actually uses the new parameter in these instances (if it writes to it, this will damage the stack). Hence the "Magic Hack." It violates the C standard and technically leads to undefined behavior.

My advice is that you either capture the call everywhere, or that you spit the function into two parts, and rename one of them. In any case, you must transfer the declaration back to the header file.

+3
source

Source: https://habr.com/ru/post/1200907/


All Articles