4

I am compiling one program called nauty. This program uses a canonical function name getline which is also part of the standard GNU C library.

Is it possible to tell GCC at compile time to use this program defined function?

Lundin
  • 195,001
  • 40
  • 254
  • 396
Shahzad
  • 1,999
  • 6
  • 35
  • 44
  • I wouldn't do that... It is unclear what you are asking, but that is either intended, or unintended misbehaviour you are trying to achieve... – ppeterka Sep 25 '13 at 09:18
  • In `C`, all functions are a part of a global namespace(as there is no way to define namespaces), I don't think it is possible. Also, it will compromise the readability of your program and hence not recommended. – HAL Sep 25 '13 at 09:20
  • @HAL Does it mean that I need to change the function name in definition and each calling point? – Shahzad Sep 25 '13 at 09:22
  • [This question](http://stackoverflow.com/q/14727814/912144) seems relevant. Not sure if duplicate. – Shahbaz Sep 25 '13 at 09:22
  • @Shahbaz Yes, that would be the simplest solution. – HAL Sep 25 '13 at 09:23

6 Answers6

6

One solution:

Now you have declaration of the function in some application .h file something like:

int getline(...); // the custon getline

Change that to:

int application_getline(...); // the custon getline
#define getline application_getline

I think that should do it. It will also fix the .c file where the function is defined, assuming it includes that .h file.

Also, use grep or "find in files" of editor to make sure that every place where that macro takes effect, it will not cause trouble.

Important: in every file, make sure that .h file included after any standard headers which may use getline symbol. You do not want that macro to take effect in those...

Note: this is an ugly hack. Then again, almost everything involving C pre-processor macros can be considered an ugly hack, by some criteria ;). Then again, getting existing incompatible code bases to co-operate and work together is often a case where a hack is acceptable, especially if long term maintenance is not a concern.

Note2: As per this answer and as pointed out in a comment, this is undefined behavior by C standard. Keep this in mind, if intention is to maintain the software for longer then just getting a working executable binary one time. But I added a better solution.

Community
  • 1
  • 1
hyde
  • 60,639
  • 21
  • 115
  • 176
4

Note that you may trigger undefined behavior if the GCC header where standard getline is defined is actually used in your code. These are the relevant information sources (emphasis mine):

The libc manual:

1.3.3 Reserved Names

The names of all library types, macros, variables and functions that come from the ISO C standard are reserved unconditionally; your program may not redefine these names. All other library names are reserved if your program explicitly includes the header file that defines or declares them. There are several reasons for these restrictions:

[...]

and the C99 draft standard (N1256):

7.1.3 Reserved identifiers

1

Each header declares or defines all identifiers listed in its associated subclause, and optionally declares or defines identifiers listed in its associated future library directions subclause and identifiers which are always reserved either for any use or for use as file scope identifiers.

[...]

2

No other identifiers are reserved. If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined.

3

If the program removes (with #undef) any macro definition of an identifier in the first group listed above, the behavior is undefined.

Thus even the macro trick suggested in another post will invoke undefined behavior if you include the header of getline in your code.

Unfortunately, in this case the only safe bet is to manually rename all getline invocations.

  • Hmm, as per man page of getline, with right defines or compiler options, it should be possible to disable getline declaration, or am,I mistaken? Then, it becomes just a linker problem, and fixing that as per my answer should be fine standards-wise. – hyde Sep 25 '13 at 15:38
  • @hyde I don't work usually on *NIX systems, so I've not direct experience of this trickery with `getline`. Disabling `getline` declaration may work, but according to the sources I cited it doesn't seem that it is guaranteed. That is, disabling `getline` declaration doesn't mean that you are free to reuse that identifier (even if not declared). In absence of a clearly spelled-out guarantee in that sense, the libc manual is clear: if you include the header you can't reuse the identifier (whether or not the header actually declares it). – LorenzoDonati4Ukraine-OnStrike Sep 25 '13 at 21:30
  • @hyde BTW, undefined behaviour doesn't necessarily mean that that trick won't work. It means that it is not guaranteed to work. It may work with a version of libc and fail miserably with another. It may work on Debian and fail on RedHat. It fully depends on the implementation and the environment. – LorenzoDonati4Ukraine-OnStrike Sep 25 '13 at 21:34
  • Well, I did some experimenting, and actually no trickery or hackery is needed. So I added another answer. – hyde Sep 26 '13 at 07:05
  • `getline` is not a standard C routine and is not a reserved identifier by the C standard, so the rules in the C standard about defining a reserved identifier as a macro name do not apply to it. – Eric Postpischil Sep 26 '13 at 13:10
  • @EricPostpischil Well, if the term "reserved" in libc manual is not to be interpreted as implicitly referring to the standard (with all those UB implications), what is the exact meaning of the term? In other words, what are we to expect when reusing a libc reserved name? – LorenzoDonati4Ukraine-OnStrike Sep 26 '13 at 19:18
  • @LorenzoDonati: `getline` is not a C standard routine and is not part of the standard C library. It is a POSIX routine. The identifier `getline` is not reserved by the C standard. POSIX is not part of the C standard. `getline` should be in a POSIX library and should not be in a standard C library. – Eric Postpischil Sep 26 '13 at 19:55
2

C demands unique function names. but you can use -fno-builtin or -ffreestanding gcc flags. see description about this flags in gcc man page.

SD.
  • 1,432
  • 22
  • 38
1

A common approach is to use prefixes which form some sort of namespace. Sometimes you can see macros used for this to make changing the namespace name easier, e.g.

#define MYAPP(f) myapp_##f

Which is then used like

int MYAPP(add)(int a, int b) {
    return a + b;
}

This defines a function myapp_add which you can also invoke like

MYAPP(add)(3, 5);
Frerich Raabe
  • 90,689
  • 19
  • 115
  • 207
  • 5
    Since this solution involves changing all calls to the function, I'd much rather just rename the function (as a 'proper' fix). – Bernhard Barker Sep 25 '13 at 09:25
  • @Dukeling: Sure, if you don't plan to change the name of the namespace (and you don't mind repeating the namespace name all over) then you can do that just as well. – Frerich Raabe Sep 25 '13 at 10:54
1

This standards compliance issue started to bug me, so I did a bit of experimenting. Here's a 2nd answer, which is possibly better then the currently accepted answer of mine.

First, solution:

Just define macro _XOPEN_SOURCE with value 699, by adding this to compiler command line options

-D_XOPEN_SOURCE=699

How exactly, that depends on applications build system, but one probably working way would be to define CFLAGS environment variable, and see if it takes effect when rebuilding:

export CFLAGS="-D_XOPEN_SOURCE=699"

Other alternative would be to add #define _XOPEN_SOURCE 699 before includes in every .c file of the application, in case it uses some esoteric build system and you can't get it added to compile options, but doing it from command line is by far preferable.

Then some explanation:

Man page of getline specifies, that getline is defined only under certain standards, such as if _XOPEN_SOURCE>=700. So, by defining a smaller value before including the relevant file, we exclude the library declaration. More information about these feature-test macros is found in GNU libc manual.

I expected there to be some linker issues too, but there weren't, and my investigation resulted this question here. To summarize, linker will prefer symbol from linked object files (at least with gcc), and will only look at dynamic libraries if it has not found symbol otherwise. So, since getline is not ISO C symbol, GNU libc documentation quoted in this answer seems to imply, that after using the _XOPEN_SOURCE trick of this answer, it's ok to use it in an application. Still, beware of other libraries using the POSIX getline and ending up calling application's function (probably with different parameters, resulting in undefined behaviour, probably a crash).

Community
  • 1
  • 1
hyde
  • 60,639
  • 21
  • 115
  • 176
  • (+1 for the research effort). I admit that the documentation involved is rather heavy. I'm not convinced I was completely wrong pointing out that potential problem, but I recognize the interpretation of all these docs may be contrived. I'm curious to see the results of your further investigations. – LorenzoDonati4Ukraine-OnStrike Sep 26 '13 at 19:23
  • @LorenzoDonati Added results of the investigation to this answer. – hyde Sep 27 '13 at 07:04
-1

Here is a neat solution to your problem. The trick is LD_PRELOAD. I have done the similar thing in one of my question post.See the following. Hack the standard function in library and call the native library function afterwards

You can defined the getline() in the separate file. This will make the design clean too. Now, compile that c file; $gcc -c -g -fPIC <file.c>. This will create the file.o. Now, make the shared object of it. -g for debugging. -fPIC for position independent code. This will help to save the RAM SIZE. The text segment will be shared, if you specify the -fPIC option.

$gcc -shared libfile.so file.o

Now, link your main file with this shared object.

gcc -g main.c -o main.out -lfile

while executing, use the LD_PRELOAD, this will use your library instead of the native API.

$LD_PRELOAD=<path to libfile.so>/libfile.so ./main.out

If you like my answer,then please appreciate. I have done the similar kind of stuff, in my previous post Hack the standard function in library and call the native library function afterwards .

Community
  • 1
  • 1
dexterous
  • 6,422
  • 12
  • 51
  • 99
  • 1
    From the gcc man page: “GCC normally generates special code to handle certain built-in functions more efficiently; for instance, calls to "alloca" may become single instructions that adjust the stack directly, and calls to "memcpy" may become inline copy loops. The resulting code is often both smaller and faster, but since the function calls no longer appear as such, you cannot set a breakpoint on those calls, nor can you change the behavior of the functions by linking with a different library.” – Eric Postpischil Sep 25 '13 at 13:09
  • yes, It could be possible. I have not gone in depth on how compiler optimizes. As the person who raised this question is looking for the option to call his/her API rather than the native API. So, This is one of the solution. Regarding, debugging you can debug it. Just build the shared object with -g option. For further details on how to hack the Native API see the following link http://stackoverflow.com/questions/18827371/hack-the-standard-function-in-library-and-call-the-native-library-function-after. In case you like my post, please appreciate. – dexterous Sep 26 '13 at 02:19