2

I'm trying to use rlutil.h but everytime these function are used in more than one header I have compiler error about multiple definition of 20-30 variables. rlutil is a simple header to color terminal in linux and windows in C and C++.

The variables are something like that

const RLUTIL_STRING_T ANSI_CONSOLE_TITLE_POST = "\007";

and the typedef something like that

typedef const char* RLUTIL_STRING_T;

I tried to add my own C guard but it didn't worked. I tried to layering the .h with my own .h/.c to make new function using the rlutil.h function but the problem is still here. I tried to make the variables extern but it's worst

I'm building it with gcc on ubuntu. I'm gonna try this at home with MVSC2017 but I think the behavior will be the same.

Any idea ?

I can provide more information. Sorry for my english i'm not a native speaker

Thank's a lot

Melio500
  • 309
  • 3
  • 9
  • It has `#pragma once`, that should prevent it from being included multiple times. – Barmar Oct 05 '17 at 17:19
  • Any chance the duplicate is in another file and that the compiler happens onto this file on accident? – Michael Dorgan Oct 05 '17 at 17:20
  • I saw that, but it doesn't – Melio500 Oct 05 '17 at 17:20
  • Reading the comments from rlutil.h - anytime I see "Here be magic" and "Here be dragons", I seriously worry that the code is not portable and may barely work on the intended target. – Michael Dorgan Oct 05 '17 at 17:22
  • The error happen like 20-30 times and I don't use that kind of variables in another files. Just including my header layer or the header 2 or more time make that happen. – Melio500 Oct 05 '17 at 17:25
  • I never had problem with the header before, it was in C++ but on a single .cpp file – Melio500 Oct 05 '17 at 17:26
  • We really need to see a [mcve] to diagnose the problem. Very likely, you would discover the issue in the course of constructing one. – John Bollinger Oct 05 '17 at 17:38
  • With that said, I have a speculation: everything you said could be explained by the presence of two copies of the header in different directories, such that both end up being included in the same translation unit. `#pragma once` does not and cannot solve this -- it is one of the main shortcomings that approach has relative to traditional multiple-inclusion guards. Traditional multiple-inclusion guards *can* solve it, but they won't if they are applied only to one copy of the header. – John Bollinger Oct 05 '17 at 17:41

1 Answers1

1

The problem is that the header is only set up so that it works with C++, where the const values defined in the header rlutil.h are private to each translation unit (TU) — think source file plus headers — that includes the header. By contrast, in C, they are normal global variables defined in each TU that includes rlutil.h, leading to the multiple definitions problem.

There isn't a trivial fix — unless switching from C to C++ is deemed trivial. The header attempts to be language-neutral between C and C++, but it fails on this count. Once again, proof that C and C++ are different languages.

In C, you would need to have code like:

extern const RLUTIL_STRING_T ANSI_CONSOLE_TITLE_POST;

in the header and then one source file would define the values:

const RLUTIL_STRING_T ANSI_CONSOLE_TITLE_POST = "\007";  // James Bond!

Alternatively, you could consider using static in the header:

static const RLUTIL_STRING_T ANSI_CONSOLE_TITLE_POST = "\007";

Each C file that includes this header would have its own collection of defined variables. In C, you'd be subject to compiler warnings about unused variables, which is not desirable. In C++, you might get warnings about using static instead of an anonymous namespace. It isn't clear that this is a good solution, therefore.

If you're brave, you could read the tail end of my answer to How do I use extern to share variables between files, but the header is probably not in your control and you really need to report the trouble to the maintainers of the code. (If you are the maintainer, then think about whether a scheme such as that outlined in the answer to the other question will help.)

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Thank's, i've just added a .c with the déclaration and made "extern" on the .h The explication is perfect and i learnt a lot – Melio500 Oct 10 '17 at 08:46