Jump to content

  • Log In with Google      Sign In   
  • Create Account


static initializers in c


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
19 replies to this topic

#1 fir   Members   -  Reputation: -397

Like
0Likes
Like

Posted 05 February 2014 - 05:55 AM

if i will wrote

 

int x = init();

 

in the static space this function init() will call even before the winmian

is called

 

I am writing c programs but compile it with c++ mode.. strange i never

used this kind of initialisers I was unaware of this.. (i think it may be handy though also maybe can bring some trouble, you must scan all the source to check what is called first etc)

 

1) I wonder is this a part of c standard as well or this is only c++ (and will not work in c)?

2) what with an order of calling this if i got more this than one (can i assume something on this order of calling or control order of it?)

3) is this generally encouraged way of writing in c (has it some downsides or pitfals?)


Edited by fir, 05 February 2014 - 05:55 AM.


Sponsor:

#2 Bregma   Crossbones+   -  Reputation: 4741

Like
7Likes
Like

Posted 05 February 2014 - 06:22 AM


1) I wonder is this a part of c standard as well or this is only c++ (and will not work in c)?

C++ inherited it from C.  It predates the standards and is a fundamental part of the language(s).

2) what with an order of calling this if i got more this than one (can i assume something on this order of calling or control order of it?)

Static initialization is always performed in lexical order within a translation unit.  The order in which static initialization is performed between translation units is undefined (and will change from build to build).

3) is this generally encouraged way of writing in c (has it some downsides or pitfals?)

I would generally discourage the use of global © or namespace-level (C++) variables.  No, really.  They effectively preclude the use of threading or unit testing and they cause maintainers to swear like sailors at the free clinic.

 

Also, because sequencing between translation units is undefined and arbitrary, it often causes unexpected trouble.


Stephen M. Webb
Professional Free Software Developer

#3 fir   Members   -  Reputation: -397

Like
0Likes
Like

Posted 05 February 2014 - 06:40 AM

 


1) I wonder is this a part of c standard as well or this is only c++ (and will not work in c)?

C++ inherited it from C.  It predates the standards and is a fundamental part of the language(s).

 

 

2) what with an order of calling this if i got more this than one (can i assume something on this order of calling or control order of it?)

Static initialization is always performed in lexical order within a translation unit.  The order in which static initialization is performed between translation units is undefined (and will change from build to build).

 

3) is this generally encouraged way of writing in c (has it some downsides or pitfals?)

I would generally discourage the use of global © or namespace-level (C++) variables.  No, really.  They effectively preclude the use of threading or unit testing and they cause maintainers to swear like sailors at the free clinic.

 

Also, because sequencing between translation units is undefined and arbitrary, it often causes unexpected trouble.

 

 

TNx for answer.

You sure this is in c? does you know in each of version of this

in the old 89 too? (strangle how long i was unaware of that if this is in c)

As to order between modules (.o files i link in mingw) isnt it maybe

dependant on command line order of this files passed tolinker..?



#4 Aardvajk   Crossbones+   -  Reputation: 5257

Like
0Likes
Like

Posted 05 February 2014 - 06:47 AM

 

As to order between modules (.o files i link in mingw) isnt it maybe

dependant on command line order of this files passed tolinker..?

 

 

It might be, but there is no standard so you can't depend on it. Might be now, then change when you update the compiler for example. That's the problem with relying on undefined behaviour.



#5 Álvaro   Crossbones+   -  Reputation: 11709

Like
0Likes
Like

Posted 05 February 2014 - 06:51 AM

As to order between modules (.o files i link in mingw) isnt it maybe
dependant on command line order of this files passed tolinker..?

 
It might be, but there is no standard so you can't depend on it. Might be now, then change when you update the compiler for example. That's the problem with relying on undefined behaviour.


The order is unspecified. "Undefined" means something else.

Edited by Álvaro, 05 February 2014 - 06:52 AM.


#6 fir   Members   -  Reputation: -397

Like
-2Likes
Like

Posted 05 February 2014 - 06:53 AM

 

 

As to order between modules (.o files i link in mingw) isnt it maybe

dependant on command line order of this files passed tolinker..?

 

 

It might be, but there is no standard so you can't depend on it. Might be now, then change when you update the compiler for example. That's the problem with relying on undefined behaviour.

 

Well if i will build this once and for all it probably will not change at

runtime - so the formula of this order for mingw would be welcome -

does anybody maybe know?

(though i know it then it is limited to some environment only)



#7 Álvaro   Crossbones+   -  Reputation: 11709

Like
2Likes
Like

Posted 05 February 2014 - 07:06 AM

You really should heed the advice you have been given.

Another piece of advice: You should avoid global variables in general, and then this problem doesn't even exist. If you do use global variables for something, initialize them explicitly.

For instance, the `main' function in my C++ chess program starts with some initializations. The exact code looks like this (comments added for you):
 
int main() {
  // This is a hook so I can do any platform-specific initializations
  platform_initialize();
  
  // The pseudo-random number generator is an example of global state
  std::srand(std::fmod(now(), 1.0)*1000000);
  
  // Precompute some lookup tables
  initialize_magics();
  initialize_square_piece_tables();
  initialize_material_hash_table();
  
  // ...
}

Edited by Álvaro, 05 February 2014 - 07:08 AM.


#8 fir   Members   -  Reputation: -397

Like
0Likes
Like

Posted 05 February 2014 - 07:21 AM

Well I chceked it 

 

 c:\mingw\bin\gcc main.c -std=c99 

 

and it does not compile, so maybe this is

not in c, though?



#9 frob   Moderators   -  Reputation: 18373

Like
3Likes
Like

Posted 05 February 2014 - 07:33 AM

It certainly exists in both.
 
C89:

If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, it is initialized implicitly as if every member that has arithmetic type were assigned 0 and every member that has pointer type were assigned a null pointer constant.

C99:

If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:
— if it has pointer type, it is initialized to a null pointer;
— if it has arithmetic type, it is initialized to (positive or unsigned) zero;
— if it is an aggregate, every member is initialized (recursively) according to these rules;
— if it is a union, the first named member is initialized (recursively) according to these rules.

The ordering requirement existed even back in the K&R book from 1978. I don't know if it was specified in the earlier compilers, but even if the ordering wasn't specified (in order within the file, each file in unspecified order) since that is the easiest way to process it that is the likely behavior.

Now with that in mind, just because you can doesn't mean you should. **DON'T RELY ON STATIC INITIALIZATION**. I have seen actual shipped games where the static initialization took over ten seconds. We wanted to beat the previous team owners into oblivion when we did the port. The previous team masked it by mandatory splash screens.

 

 

Well I chceked it 

 c:\mingw\bin\gcc main.c -std=c99 

and it does not compile, so maybe this is not in c, though?

Post your exact error message and the relevant lines and surrounding code indicated by the actual error messages. The concept of static initialization is probably not the bug.


Check out my personal indie blog at bryanwagstaff.com.

#10 fir   Members   -  Reputation: -397

Like
0Likes
Like

Posted 05 February 2014 - 07:34 AM

You really should heed the advice you have been given.
 

 

many people give me advices with wich i generally agree (though i also

know 90%  of this advices so it is a bit strange to read advices i know of)

I am asking on some things often not because i want to do this but just to know how it works



#11 fir   Members   -  Reputation: -397

Like
0Likes
Like

Posted 05 February 2014 - 07:38 AM

It certainly exists in both.
 
C89:

If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, it is initialized implicitly as if every member that has arithmetic type were assigned 0 and every member that has pointer type were assigned a null pointer constant.

C99:

If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:
— if it has pointer type, it is initialized to a null pointer;
— if it has arithmetic type, it is initialized to (positive or unsigned) zero;
— if it is an aggregate, every member is initialized (recursively) according to these rules;
— if it is a union, the first named member is initialized (recursively) according to these rules.

The ordering requirement existed even back in the K&R book from 1978. I don't know if it was specified in the earlier compilers, but even if the ordering wasn't specified (in order within the file, each file in unspecified order) since that is the easiest way to process it that is the likely behavior.

Now with that in mind, just because you can doesn't mean you should. **DON'T RELY ON STATIC INITIALIZATION**. I have seen actual shipped games where the static initialization took over ten seconds. We wanted to beat the previous team owners into oblivion when we did the port. The previous team masked it by mandatory splash screens.

 

 

Well I chceked it 

 c:\mingw\bin\gcc main.c -std=c99 

and it does not compile, so maybe this is not in c, though?

Post your exact error message and the relevant lines and surrounding code indicated by the actual error messages. The concept of static initialization is probably not the bug.

main.c :
 
int init() {}
int x = init();
int main() {return 0;}
 
 
>c:\mingw\bin\gcc main.c -std=c99
main.c:2: initializer element is not constant
 
ps.  maybe i gave it a bad name "static initializers" but i didnt know how to name such static (global) space initialization thing like "int x = init();" so i called it here "static initializers" (maybe "static space initializers" would be better here

Edited by fir, 05 February 2014 - 07:46 AM.


#12 Álvaro   Crossbones+   -  Reputation: 11709

Like
3Likes
Like

Posted 05 February 2014 - 07:46 AM

Actually, I don't think C allows for initialization of global variables by calling a function, despite what Bregma and others have said.

 

I guess we have all been programming in C++ for too long. :)



#13 Bregma   Crossbones+   -  Reputation: 4741

Like
4Likes
Like

Posted 05 February 2014 - 10:12 AM

Álvaro is right.

ISO/IEC 9899 [6.7.8](4) All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.


Stephen M. Webb
Professional Free Software Developer

#14 Aardvajk   Crossbones+   -  Reputation: 5257

Like
0Likes
Like

Posted 05 February 2014 - 10:32 AM

 

 

As to order between modules (.o files i link in mingw) isnt it maybe
dependant on command line order of this files passed tolinker..?

 
It might be, but there is no standard so you can't depend on it. Might be now, then change when you update the compiler for example. That's the problem with relying on undefined behaviour.

 


The order is unspecified. "Undefined" means something else.

 

 

Sure you are correct but out of curiosity, what is the difference?



#15 Álvaro   Crossbones+   -  Reputation: 11709

Like
2Likes
Like

Posted 05 February 2014 - 10:57 AM

If global variables are initialized in an unspecified order, they will be initialized, you just don't know in what order. If you write a program that invokes undefined behavior, all bets are off: You can't predict what will happen at all.

 

Here's a good description of undefined behavior: http://blog.regehr.org/archives/213



#16 SeanMiddleditch   Members   -  Reputation: 3567

Like
2Likes
Like

Posted 05 February 2014 - 11:10 AM

Sure you are correct but out of curiosity, what is the difference?


Undefined, unspecified and implementation-defined behavior

#17 King Mir   Members   -  Reputation: 1889

Like
4Likes
Like

Posted 05 February 2014 - 10:52 PM

Note that since the order of initialization is unspecified, and using an object before it is constructed in undefined, having code that is sensitive to order of initialization across translation units is usually (always?) undefined behavior.

#18 Aardvajk   Crossbones+   -  Reputation: 5257

Like
0Likes
Like

Posted 06 February 2014 - 03:02 PM

 

Sure you are correct but out of curiosity, what is the difference?


Undefined, unspecified and implementation-defined behavior

 

 

3.4.4 1 unspecified behavior use of an unspecified value, or other behavior where this International Standard provides two or more possibilities and imposes no further requirements on which is chosen in any instance

 

How is the order of statics across translation units unspecified then? Does the standard provide one or more standard orders? I thought it was undefined across different translation units.

 

[EDIT] Actually after reading that link's definition of "undefined" I guess it does make some sense. I always thought "undefined" was anything that was not specified by the standard but if "undefined" requires non-portable or erroneous data or program constructs, "unspecified" I guess covers everything else that is undefined but not erroneous. I suppose "undefined" is where even the compiler makes no guarantee of what will happen, regardless of standard and "unspecified" is where the compiler is doing something predictable and deterministic but not something the standard enforces.


Edited by Aardvajk, 06 February 2014 - 03:06 PM.


#19 King Mir   Members   -  Reputation: 1889

Like
0Likes
Like

Posted 06 February 2014 - 03:27 PM

Yeah, undefined behavior means your code is not C++, as defined by the C++ standard.

Undefined behavior has also been called "catch fire semantics" to underscore the fact that anything can happen, even your computer going ablaze, when undefined behavior is invoked.

Edited by King Mir, 06 February 2014 - 03:31 PM.


#20 SeanMiddleditch   Members   -  Reputation: 3567

Like
1Likes
Like

Posted 06 February 2014 - 05:21 PM

How is the order of statics across translation units unspecified then? Does the standard provide one or more standard orders?


Yes, the standard does provide one or more possible orderings. The options available to the implementation are all of the ordering permutations of the translation units. Initializing all the statics of A.obj before B.obj is just as valid as doing B.obj before A.obj. The standard guarantees that they're all linked together and their statics will be initialized in some order. How that order is determined is not specified by the standard and each implementation is free to order them however it wants, even differently between successive runs.

If the implementation were expected to order TU initialization in a self-consistent manner then the behavior would be implementation-defined instead of unspecified. This is not a requirement the standard wanted to place on implementations. The implementation may not even be in control of the choice such as in a multi-threaded linker (so the statics initialized first are dependent on whichever translation unit's worker thread happened to be scheduled by the OS to run first). If the standard wanted to place restrictions on the implementation so that you the user could predict the initialization order on every conforming implementation (even if it differed between implementations), the standard would have made this behavior implementation-defined and whole classes of possible compilation optimizations would be illegal.

If the behavior were undefined behavior then that would mean that the TUs' static objects may be initialized in some order clearly documented by the implementation, or the implementation can elect to initialize only some of them and not document how it makes that choice, or all of them may be left uninitialized, or they all might be initialized to the same value as one of them, or the implementation may raise an error and abort upon seeing any static initializations, or the implementation could happily generate code that causes a CPU exception. Every implementation could do something different and none of them would be considered buggy in terms of standards compliance. Undefined behavior has a beneficial purpose in places but certainly not for static initialization ordering.

Edited by SeanMiddleditch, 06 February 2014 - 05:23 PM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS