Problem with extern keyword in C++ - c++

What's the difference between the following two declarations? I thought they were equivalent, but the first sample works, and the second does not. I mean it compiles and runs, but the bitmap display code shows blank. I have not stepped through it yet, but am I missing something obvious? GUI_BITMAP is a simple structure describing a bitmap. This is for VC++ 2005, but I think it fails in VC++ 2008 also. Scratching my head on this one...
Sample 1:
extern "C" const GUI_BITMAP bmkeyA_cap_active;
extern "C" const GUI_BITMAP bmkeyA_cap_inactive;
Sample 2:
extern "C"
{
const GUI_BITMAP bmkeyA_cap_active;
const GUI_BITMAP bmkeyA_cap_inactive;
};
Edit: More exploring has shown that the second example is creating the structs, while the first is referring to external structs. The second example should fail to link, since there are two variables at global scope with the same name. But it doesn't, it sends a zero filled struct to the display code which gives up. Hmmm.....
Edit 2: Running the same code through another compiler (IAR) actually failed to compile on Sample 2, with an error about missing a default constructor. So I'm guessing there is something subtle about the "extern" keyword, structs, and C++ that I don't get. If the things in extern area were functions the two samples would be identical right?

Your linker may is silently resolving the duplicate symbols behind your back. You might get static libraries from a vendor and have to link them with your program - what is the solution for the situation where you have two such libraries and they both define a common symbol? The linker will just resolve that, choosing one or the other definition, and leaving you to deal with the fallout. How are you handling the link stage of your application? You may have better results if you link .o files directly instead of putting them into intermediate libraries before linking the final application.
This page of the ARM documentation describes the problem well - I expect similar behaviour is happening in your case:
Multiple definitions of a symbol in different library objects are not necessarily detected. Once the linker has found a suitable definition for a symbol it stops looking for others. Assuming the object containing the duplicate symbol is not loaded for other reasons no error will occur. This is intentional and particularly useful in some situations.
Edit: More searching has turned up that this problem is caused because of a violation of the "One Definition Rule", and as a result the compiler/linker aren't required to inform you of the problem. That makes your question a duplicate of this one.

The second example might be equivalent to the first with an extra extern in front of the const. In the first case, the compiler is probably combining the two uses of extern. In the second case, I would assume the compiler doesn't male everything in the extern scope extern for whatever reason.

Related

Why can I link two libraries exporting the same C-Function in VC?

I have the situation that two C++ Libraries export the very same C-function symbols from shared code. When I now compile an executable which links both libraries, I do not get any linker error or warning from VC12. Why is this? It silently just chooses one of the two symbols and I have no idea which one is chosen.;
extern "C" { __declspec(dllexport) int function(void* argument);}
There is a flag named /FORCE which whould be able to convice VC to compile even if there are multiply defined symbols, but this flag is not set.
I do not find any official information from Microsoft why this links at all. I was expecting to get a LNK4006 warning, but I don't.
I just want to know if this is the expected or undefined behavior, which only did not explode by coincidence. I read things about the One Definition Rule not being applied generally to C-Code, but I cannot find any reliable statement for the VC compiler.
Can I assume that, given the functions do not use any singletons, use the very same code and compiler flags, it does not matter which one is chosen?
You are violating the one definition rule.
The behavior of you program is undefined.
See section "3.2 One definition rule [basic.def.odr]" in the C++ standard.
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required. ...
Section 3.2.6 describes when there can be more than one definition
of a class type, inline function with external linkage etc. in a program.
I just want to know if this is the expected or undefined behavior, which only did not explode by coincidence. I read things about the One Definition Rule not being applied generally to C-Code, but I cannot find any reliable statement for the VC compiler.
It is undefined behavior.
The C++ standard is the master, not the VC compiler.
Can I assume that, given the functions do not use any singletons, use the very same code and compiler flags, it does not matter which one is chosen?
It is still undefined behavior - though the program might appear to behave as expected.

Extern variable only in header unexpectedly working, why?

I'm currently updating a C++ library for Arduino (Specifically 8-bit AVR processors compiled using avr-gcc).
Typically the authors of the default Arduino libraries like to include an extern variable for the class inside the header, which is defined in the class .cpp file also. This I assume is basically to have everything provided ready to go for newbies as built-in objects.
The scenario I have is: The library I have updated no longer requires the .cpp file and I have removed it from the library. It wasn't until I went on a final pass checking for bugs that I realized, no linker error was produced despite the fact a definition wasn't provided for the extern variable in a .cpp file.
This is as simple as I can get it (header file):
struct Foo{
void method() {}
};
extern Foo foo;
Including this code and using it in one or many source files does not cause any linker error. I have tried it in both versions of GCC which Arduino uses (4.3.7, 4.8.1) and with C++11 enabled/disabled.
In my attempt to cause an error, I found it was only possible when doing something like taking the address of the object or modifying the contents of a dummy variable I added.
After discovering this I find its important to note:
The class functions only return other objects, as in, nothing like operators returning references to itself, or even a copy.
It only modifies external objects (registers which are effectively volatile uint8_t references in code), and returns temporaries of other classes.
All of the class functions in this header are so basic that they cost less than or equal to the cost of a function call, therefore they are (in my tests) completely in-lined into the caller. A typical statement may create many temporary objects in the call chain, however the compiler sees through these and outputs efficient code modifying registers directly, rather than a set of nested function calls.
I also recall reading in n3797 7.1.1 - 8 that extern can be used on incomplete types, however the class is fully defined whereas the declaration is not (this is probably irrelevant).
I'm led to believe that this may be a result of optimizations at play. I have seen the effect that taking the address has on objects which would otherwise be considered constant and compiled without RAM usage. By adding any layer of indirection to an object in which the compiler cannot guarantee state will cause this RAM consuming behavior.
So, maybe I've answered my question by simply asking it, however I'm still making assumptions and it bothers me. After quite some time hobby-coding C++, literally the only thing on my list of do-not's is making assumptions.
Really, what I want to know is:
With respect to the working solution I have, is it a simple case of documenting the inability to take the address (cause indirection) of the class?
Is it just an edge case behavior caused by optimizations eliminating the need for something to be linked?
Or is plain and simple undefined behavior. As in GCC may have a bug and is permitting code that might fail if optimizations were lowered or disabled?
Or one of you may be lucky enough to be in possession of a decoder ring that can find a suitable paragraph in the standard outlining the specifics.
This is my first question here, so let me know if you would like to know certain details, I can also provide GitHub links to the code if needed.
Edit: As the library needs to be compatible with existing code I need to maintain the ability to use the dot syntax, otherwise I'd simply have a class of static functions.
To remove assumptions for now, I see two options:
Add a .cpp just for the variable declaration.
Use a define in the header like #define foo (Foo()) allowing dot syntax via a temporary.
I prefer the method using a define, what does the community think?
Cheers.
Declaring something extern just informs the assembler and the linker that whenever you use that label/symbol, it should refer to entry in the symbol table, instead of a locally allocated symbol.
The role of the linker is to replace symbol table entries with an actual reference to the address space whenever possible.
If you don't use the symbol at all in your C file, it will not show up in the assembly code, and thus will not cause any linker error when your module is linked with others, since there is no undefined reference.
It is either an edge case behaviour caused by optimization, or you never use the foo variable in your code. I'm not 100% sure it is formally not an undefined behavior, but i'm quite sure it isn't undefined from practical point of view.
extern variables are implemented in such way, that code compiled with them produces so-called relocations - empty places where addres of variable should be placed - which are then filled by linker. Apparently foo is never used in your code in such a way that would need getting it's address and therefore linker doesn't even try to find that symbol. If you turn optimization off (-O0) you will probably get linker error.
Update: If you want to keep "dot notation" but remove the problem with undefined extern, you may replace extern with static (in header file), creating separate "instance" of variable for each TU. As this variable is going to be optimized out anyway, this will not change the real code at all, but will also work for unoptimized build.

OpenGL GLSL GLUT conflict

Ok, I am trying to make an OpenGL Application to use a Fragment Shader. I need to get some variables into the fragment shader using glUniform.
I've seen some examples that look like this:
static PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
they have like 10 of those. When I put them in, it says, previous declaration of glShaderSourceARB, or glShaderSourceARB was declared 'extern' and then later 'static'.
When I DON'T put it in, every time I use glShaderSourceARB, I get an Undefined Reference to glShaderSourceARB.
HOW is this possible? It gets mad at me for declaring it twice, but if I take out 1 declaration, it says its not declared at all. Can someone explain how this is supposed to work?
Okay, your problem stems from lack of knowledge about C storage and scope qualifiers.
static in the global scope means: This symbol is visible to only the compilation unit its in and only that compilation unit. Other compilation units may have static symbols of the same name, but those are their own private symbols as well and they don't interfere.
extern means, that the symbol it refers to is defined and exposed (i.e. not static) somewhere else unit. You normally use it in headers. While it's certainly possible to write extern static this usually makes little sense to do.
Now what you did was introducing a new, global symbol with static scope, while the header already declared a not static symbol of the same name to exist. And the compiler tells you "sorry, this name is already taken; but your symbol doesn't match the extern declaration, so get lost."
However with just a extern declaration, but no actual definition of the symbol, the linker will at the end tell you: "There are a few parts missing, where is xyz, did nobody actually define it; everybody is referring to it (extern), but nobody actually provides it."
Okay, so should you define glShaderSourceARB as non-static then? No!
Because having that symbol around does not suffice. You also have to initialize it to something. For that you use glXGetProcAddress or wglGetProcAddress. You have to call that with the function name, for each and every symbol. And because in Windows the function addresses may depend on the active OpenGL context you have to put those symbols into thread local storage and reinitialize them everytime wglMakeCurrent is called.
What you really should do is get yourself a library that does all this tedious work drop it into your program and no longer think about it. Like GLEW, available at http://glew.sourceforge.net – read the documentation carefully, follow each step and things will work (if you follow the documentation). A word of recommendation: Embedding GLEW statically simplifies program distribution.
You evidently have a header where the function signatures are declared, but you don't have any library linked, which would actually contain the functions (that is the undefined reference error).
In Windows, the library does not contain shader functions (only functions up to OpenGL 1.1) and some third party library such as GLEW or GLEE is a must. You can also see how MiniShader is implemented (it does what GLEW / GLEE do, except it is optimized for minimal code size, such as in 4k intros).
In Linux, just linking with -lGL could help linking with the OpenGL library abd thus avoiding undefined references (if not, then use GLEW just as well).

symbol not found AKA undefined symbol

Most of the people who work on UNIX will face this irritating error often.
and some times it will take less time to solve and sometimes it will take hell lot of time.
Even i faced this regularly and i need some good document or an article regarding the specific error in c/c++
what are all the cases where there might be Symbol not found/Undefined Symbol error.
Could anybody help me to know what are all those cases?
The error is not related to UNIX/Windows/any other OS, but rather to the languages themselves. It is actually rather simple to diagnose with the information that compilers provide. Usually they will tell you what symbol is missing and sometimes where it is being used. The main reasons for a symbol to be missing are:
You have declared but never defined it
You have defined it, but did not add the compiled symbol (object file/library) to the linker
It is external and you forgot to link the library, or you are linking an invalid version, or in the wrong order.
The first one is a little trickier if you intended to define the symbol but did not match the declaration (declared void foo( int, double );, but defined void foo( double, int ). As with all other cases, the compiler will tell you the exact signature that it is looking for, make sure that you have defined that symbol, and not something close or similar, a particular corner case can be if you are using different calling conventions in the declaration and the definition, as they will look very similar in code.
In the case of libraries external code the complexity is in identifying what library needs to be linked for that symbol to be added, and that comes from the documentation of the lib. Beware that with static libraries the order of the libs in the linker command line affects the result.
To help you in finding what symbols are actually defined you can use nm (gcc, which is common among unix systems). So basically you can run nm against the object files/libs that you are linking and search for the symbol that the linker is complaining about. This will help in cases where the order is what makes the difference (i.e. the symbol is there, but the linker skipped it).
At runtime (thanks to Matthieu M. for pointing it out) you might have similar issues with dynamic libraries, if the wrong version of a library is found in the LD_LIBRARY_PATH you might end up with a library that does not have a required symbol.
Although they can be platform dependent, I have some "more complex" instances of some of the points from Andreas and David:
When dealing with shared libraries (.so or.dll) and linking against symbols which are not exported (dllimport/dllexport on Windows and visibility("default") with GCC on *nix)
Or similar: Linking against the static lib, while expecting a shared lib or vice versa. This one is bit similar to Mathieu's comment about linking against another, unexpected version of the library.
Creating a pure virtual classs and not providing an implementation for at least one method (causing no vtable to be available).
Actually a more complex case of declaring but not defining: The linking errors you can get when dealing with large, nested templates. Finding out what was not defined can be difficult with large error messages.
For most cases when you get a symbol not found/undefined symbol or sometimes even a "duplicate symbol" error, they usually stem from the fact that the linker is unable to find the symbol in the project that you are trying to build.
The best way to go about it is to look at the map file generated or a symbol table that is the output of the compiler. It may look something like this:
This will allow you to see if the symbol is present or not. Also, there might be other esoteric problems such as compiler optimizations that might cause a symbol duplication especially with inline assembly. These are about the hardest to detect.
As for good resources and materials, I don't have many good references. When I did ask around back then, most of the senior engineers have actually learned from their own experiences.
But I'm sure that's where forums such as these are present to help us expedite such knowledge acquisition.
Hope it helped :)
Cheers!
I assume you're referring to the linker error. Here's a list from the top of my head in what I think most-to-least common:
You forgot to tell the linker about a dependency (e.g. a LIB-file).
You have a class with a static data member and forgot to initialize it (only C++).
You declared a function not purely virtual and forgot to implement it.
You forgot to implement a function that you called from another function (only C, C++ will give a compiler error which is much easier to find).
You declared an external variable and forgot to initialize it.
The declaration of the function doesn't match the implementation (only C++, C will accept it and might die horribly).
You forgot to implement a function that you declared and called from another function.

Function declarations and an unresolved external

I am looking after a huge old C program and converting it to C++ (which I'm new to).
There are a great many complicated preprocessor hacks going on connected to the fact that the program must run on many different platforms in many different configurations.
In one file (call it file1.c) I am calling functionA().
And in another file (call it file2.c) I have a definition of functionA().
Unfortunately the exact type of the function is specified by a collection of macros created in a bewildering number of ways.
Now the linker is complaining that:
functionA is an unresolved external symbol.
I suspect that the problem is that the prototype as seen in file1.c is slightly different from the true definition of the function as seen in file2.c.
There is a lot of scope for subtle differences due to mismatches between _cdecl and fastcall, and between with and without __forceinline.
Is there some way to show exactly what the compiler thinks is the type of functionA() as seen by file1.c as opposed to file2.c?
You can pass a flag to the compiler (/P, I think) that causes it to output the complete preprocessed output that is passed to the compiler - you can then open this (huge) file, and search through it and the information you need will be in there, somewhere.
Must you actually convert all the existing C code to C++? This is likely to be a lot of work, especially given what you've described so far.
Instead, you can write new code in C++ and call into the C code using extern "C". For example, in a C++ source file you can:
extern "C" {
#include "old_c_header.h"
}
This changes the linkage so the C++ compiler generates external references to the C code without name mangling, allowing the linker to match everything up.
Normally you should have the expected and the actual signature in the output.
Otherwise you can instruct the compiler to output the results of the preprocessing into a seperate file, cl.exe /p for MSVC and for gcc gcc -E.