ODR@functions(+classes)

OneDefinitionRule is more strict on global variables (which have static duration). You can’t have 2 global variables sharing the same name. Devil is in the details:

As explained in various posts, you declare the same global variable in a header file that’s included in various compilation units, but you allocate storage in exactly one compilation unit. Under a temporary suspension of disbelief, let’s say there are 2 allocated storage for the same global var, how would you update this variable?

With free function f1(), ODR is more relaxed. http://www.drdobbs.com/cpp/blundering-into-the-one-definition-rule/240166489 explains the Lessor ODR vs Greater ODR. My focus today is the Greater ODR therein. The same function can be included via a header file into multiple compilation units and goes into multiple binaries. Two copies of this function are usually identical definitions. If they actually have different definitions, compiler/linker can’t easily notice and are not required to verify, so no build error (!) but you get could strange run time errors.

Java linker is simpler and never cause any problem so I never look into it.

example with/without extern-C

---- dummy8.c ----
#include <stdio.h> //without this "test", we could be using c++ compiler unknowingly 😦
int cfunc(){ return 123; }
---- dummy9.cpp ----
#include <iostream>
extern "C" // Try removing this line and see the difference
  int cfunc();
int main(){std::cout << cfunc() <<std::endl; }

Above is a complete example of a c++ application using a pre-compiled C function. It shows the need for extern-C.

/bin/rm -v *.*o *.out

gcc -v -x c -c dummy8.c # Without the -x c, we would end up with c++ compiler 😦

g++ -v dummy8.o dummy9.cpp  # link the dummy8.o into executable

./a.out

So that’s how to compile and run it. Note you need both a c compiler and a c++ compiler. If you only use a c++ compiler, then you won’t have the pre-compiled C code. You can still make the code work, but you won’t be mixing C and C++ and you won’t need extern-C.

My goal is not merely “make the code work”. It’s very easy to make the code work if you have full source code. You won’t need extern-C. You have a simpler alternative — compile every source file in c++ after trivial adjustments to #include.

c++dynamicLoading^dynamicLinking^staticLinking, basics

https://en.wikipedia.org/wiki/Dynamic_loading

*.so and *.dll files are libraries for dynamic linking.
*.a and *.lib files are libraries for static linking.

“Dynamic loading” allows an executable to start up in the absence of these libraries and integrate them at run time, rather than at link time.

You use dlopen(“path/to/some.so”) system call. In Windows it’s LoadLibrary(“path/to/some.dll”)

c++class field defined]header yet !local vars obey ODR

Let’s put function declaration/definition aside — much simpler.

Let’s put aside local static/non-static variables — much simpler. Let’s put aside function parameters. They are like local variables.

The word “static” is heavily overloaded and confusing. I will try to avoid it as far as possible.

The tricky/confusing categories are

  • category: static field. Most complex and better discussed in a dedicated post — See https://bintanvictor.wordpress.com/2017/02/07/c-static-field-init-basic-rules/
  • category: file-scope var — i.e. those non-local vars with “static” modifier
  • category: global var declaration — using “extern”
    • definition of the same var — without “extern” or “static”
  • category: non-static class field, same as the classic C struct field <– the main topic in the post. This one is not about declaration/definition of a variable with storage. Instead, this is defining a type!

I assume you can tell a variable declaration vs a variable definition. Our intuition is usually right.

The Aha — [2] pointed out — A struct field listing is merely describing what constitutes a struct type, without actually declaring the existence of any variables, anything to be constructed in memory, anything addressable. Therefore, this listing is more like a integer variable declaration than a definition!

Main reason to keep struct definition in header — compiler need to calculate size of the struct. Scott Meyers discussed this in-depth along with class fwd declaration and pimpl.

See also

global^file-scope variables]c++

(Seldom quizzed…) This topic is all about lingo..

The word “static” is heavily overloaded and confusing. I will try to avoid it as far as possible.

Any object declared outside a block has “static duration” which means (see MSDN) “allocated at compile time not run time”

“Global” means extern linkage i.e. visible from other files. You globalize a variable by removing “static” modifier if any.

http://stackoverflow.com/questions/14349877/static-global-variables-in-c explains the 2+1 variations of non-local object

  • a single “static” variable in a *.cpp file. The “static” makes this variable visible only to this file.
  • an extern variable. I used this many times. Basically in one *.cpp it’s declared without “static” or extern. In other *.cpp files, it’s declared extern without a initial value.
  • wrong way — if you (use a shared header to) declare the same variable “static” in 2 *.cpp files, then each file gets a distinct file-scope variable of the same name. Nonsense.

“File-scope” means internal linkage i.e. visible only within the file. You make a variable file-scope by adding “static”.

https://msdn.microsoft.com/en-us/library/s1sb61xd.aspx

http://en.wikipedia.org/wiki/Global_variable#C_and_C.2B.2B says “Note that not specifying static is the same as specifying extern: the default is external linkage” but I doubt it.

I guess there are 3 forms :

  • static int — file-scope, probably not related to “extern”
  • extern int — global declaration of a var already Defined in a single file somewhere else
  • int (without any modifier) — the single definition of a global var

linker dislikes(non-generic)function definition in shared header

I used to feel header files are optional so we can make do without them if they get in our ways. This post shows they aren’t optional in any non-trivial c++ project. There is often only one (or few) correct way to structure the header vs implementation files. You can’t make do without them.

Suppose MyHeader.h is included in 2 cpp files and they are linked to create an executable.

A class definition is permitted in MyHeader.h:

class Test89{
void test123(){}
};

However, if the test123() is a free function, then linker will fail with “multiple definition” of this function when linking the two object files.

http://stackoverflow.com/questions/29526585/why-defining-classes-in-header-f iles-works-but-not-functions explains the rules

* repeated definition of function (in a shared header) must be inlined * repeated class definition (in a shared header) is permitted for a valid reason (sizing…). Since programmers could not only declare but define a member function in such a class, in a header, the compiler silently treats such member functions as inline