Can I declare a global variable inside a library that is later compiled into a shared object ? Is it safe to reference it from other libraries or the main application code by de
Shared libraries are not a C concept. The shared library implementations of different operating systems and computing platforms, where they exist, exhibit differences in form and behavior.
Nevertheless, yes, all shared library implementations of which I am aware do support variables with, from a C perspective, static storage duration and external linkage, which I assume is what you mean by "global". Inasmuch as you appear to be using Linux, your shared libraries will be of the ELF flavor. In that case, each process that dynamically links the shared library will get its own copy of such variables.
The large variable address you describe is of no particular consequence. ELF shared libraries do not have to be loaded at any particular address, and in fact Linux implements ASLR, which actively makes library load addresses vary. Your shared library can be loaded more or less anywhere in your system's 64-bit virtual address space, so you really can't read much into the fact that the variable's address is numerically large.
As for the bug you describe, I'm inclined to think it arose from bad code, not (directly) from the involvement of a shared library. From your description, I suspect that you ended up with multiple variables with the same name, all with external linkage. That's an error with static linking, but in that case the compiler can (and by default, GCC does) merge the duplicate variables instead of rejecting the code.
With ELF, on the other hand, it's ok for the same symbol to be defined in multiple shared objects linked into the same process, and different definitions can be referenced from different points in the overall process. Since a shared library is compiled separately from the main program, the compiler does not have an opportunity to merge symbols, and it's not obvious that it should even if it could. But multiple declarations of a given symbol is a possibility not a necessity. If it happens, it's probably because your headers declare the variable wrongly.
There may be many declarations of any given variable in a program, but there must be exactly one definition. The declarations typically come from a header file, and they should look like this:
extern int foo;
The extern
is mandatory if the header is to be used in more than one source file -- that and the absence of an initializer establish that the declaration cannot be interpreted as a definition. There should then be a definition of the variable in exactly one source file, looking something like this:
int foo = 0;
The presence of an initializer establishes that the declaration is also a definition. It might still be a definition if the initializer were omitted, as long as the extern
qualifier is not included, but if you don't want to learn all the details then it's safe to just provide an initializer.
A problem such as you describe will arise if there are definitions of foo
in multiple shared objects. That would happen if, for example, a header file contained a declaration of either of these forms:
int foo; /* WRONG - without extern, this is a tentative definition */
extern int bar = 0; /* WRONG - because of the initializer, this is a definition */
Yes, libraries can contain global variables.
But depending on compiler/linker options, they might be not visible. E.g. it is common practice, that libraries are built with -fvisibility=hidden
and that only certain symbols are exported (by linker map or explicit __attribute__((__visibility__))
tags).
Your "large" project has been probably built in such a way.
The high address might also indicate, that variable
is some kind of other symbol (function) in another library.