Look at this code:
#include <framework_i_hate.h>
int main() {
XFile file("./my_file.xxxx", "create");
XObject object("my_object");
// modify the object
object.Write();
}
Try to guess where object will be saved... yes, you guessed it. I think this is too magic, I'd like to write something like object.Save(file), but it's not necessary. Obviously there is global variable inside framework_i_hate.h that it is modified during the file constructor. What do you think about this side effect inside constructor?
How can this behavior be hidden?
A bonus to who guess the framework.
Very muddled hard to understand post and the question in the end is very rhetorical.
Global variables are evil, what else to add?
What can be said about this that isn't already obvious enough: It's a fairly nasty side effect, because:
the resulting behaviour is unexpected and not predictable at all, unless you know that framework well.
global program state usually isn't a good idea in object-oriented programming. (In fact, global state is probably never a good idea, so best avoid it if you can.)
it's fairly likely that this framework isn't thread-safe, either. (Think about what happens when two concurrent threads both create an XFile object each, and one of these threads then writes an XObject... where will it end up being saved?)
While this thread is tagged C++ and not about .NET, I have seen this "anti-pattern" before in a less severe and much more sane form, namely with DB transaction scopes.
I'd prefer to see the relationship between XFile and XObject be explicit, I agree that this "magic" is too well hidden. I also question why the object is given a name, unless there are other parts of the API where the name is significant.
Global variables are despised for many reasons, this is just one example.
Related
I know that C++ also allows to create global objects of class and struct.
#include <iostream>
using std::cout;
class Test
{
public:
void fun()
{
cout<<"a= "<<a;
}
private:
int a=9;
};
Test t; // global object
int main()
{
t.fun();
return 0;
}
When & where should i use global objects? Is there any specific use of global objects? Please help me.
The short answer is there is no need.
The long answer is that it can sometimes be convenient. Unfortunately convenience is subjective, and what one finds to convenient another might find to be too lenient.
Global objects have issues (among which muddying data flows in the code and access synchronization), but sometimes one might find it convenient nonetheless to use one because it makes something easier. It can indeed remain easier, or it can prove a maintenance burden, but that only the future can tell...
... If you can avoid global objects, in general you should be better off. In practice, though, you will rarely encounter issues before programming at scale; for toy examples and students' projects there is rarely an issue, which is why beginners fail to understand why more seasoned developers avoid them like the plague.
In a complex project, you shouldn't. You should always be within a namespace if you plan to use you're assembly in other projects.
An example of something that might be that high in scope is an operator overload or an interface that you define which will be used many times.
Good practice...organize your project to use descriptive and intuitive namespaces.
Global is really only useful in simple project that simple don't use namespaces.
The question is malposed: is there a need for if wile and do, since we can do all with just for ?
The technical answer is "no, there is no need: the fact we can do without proves it". But a little more pragmatism show us that reducing every control flow into a single keywork makes code harder to track and follow. So it is technically possible but not always convenient.
Now: can we do without global objects?
A first non-answer is "yes, with singletons". But a singleton is a static object obtained through a function. They are not that conceptually different if not for a design flaw (known as "static initialization order fiasco") due to C++ not specifying global initialization object order essentially to allow multiple translation unit to coexist in a same linked executable. Singleton allow to circumvent that problem, but are essentially a workaround to allow global "things" to exist.
The existence of that flaw (and the singleton technique) is wat makes many "teachers" to draw some "moral" suasion like "never use global objects, or the flame of hell will burn your ass-hair". But that soon do std::cout << "hello world" and immediately loose ALL their credibility.
The point is that without "globals" everything is "scope local" and there is no "dynamic scope" in C++: if funcA calls funcB, funcB cannot see funcA locals, hence the only way to access things across scopes is parameter passing of reference or pointers.
In context which are mostly "functional", the missing of "dynamic scopes" is compensated by "lamba captures", and everything else will go as paramenter.
In context which are mostly "procedural", the need of a "state" that survives scopes and can be modified while going in and out is more suited for global objects. And that's the reason cout is that. It represent a resource theat pre-exist and post-exist the program, whose state evolves across various calls. If there is no global way to access cout, it should be initialized in main, an passed as a reference parameter to whatever function call: even the one that have no output to give, since they may call themselves something else that has output to give.
In fact you can think to global object as "implicit parameters passed to every function".
You can warp in global functions but -if functions themselves can be objects and object themselves can be functional- why saying global objects are bad and global functions can be right?
The actual only reason, in fact, turns out to be the static initialization order fiasco
I would say that global variables are needed for backwards compatibility with c. That is for sure, and this is the only hard reason I see. Since classes and structs are essentially the same, it probably didn't make much sense in forbidding only one.
I don't know any patterns or use-cases that are universally accepted as a good practice, that would make use of global objects. Usually global objects, sooner or later, lead to mess if not interacted with properly. They hide data flow and relationships. It is extremely easily to trip over it.
Still, I have seen some libraries exposing some objects as globals. Usually things that contain some static data. But there are other cases too, notable example being standard library's std::cout and family.
I won't judge if it's good or bad approach. This is too subjective IMO. You could probably use singletons, but one might argue, you can work on a global object under a contract etc. etc.
Recently a fellow worker showed to me a code like this:
void SomeClass::function()
{
static bool init = false;
if (!init)
{
// hundreds of lines of ugly code
}
init = true;
}
He wants to check if SomeClass is initialized in order to execute some piece of code once per Someclass instance but the fact is that only one instance of SomeClass will exist in all the lifetime of the program.
His question were about the init static variable, about when it's initialized. I've answered that the initialization occurs once, so the value will be false at first call and true the rest of its lifetime. After answering I've added that such use of static variables is bad practice but I haven't been able to explain why.
The reasons that I've been thinking so far are the following:
The behaviour of static bool init into SomeClass::function could be achieved with a non-static member variable.
Other functions in SomeClass couldn't check the static bool init value because it's visibility is limited to the void SomeClass::function() scope.
The static variables aren't OOPish because they define a global state instead of a object state.
This reasons looks poor, unclever and not very concrete to me so I'm asking for more reasons to explain why the use of static variables in function and member-function space are a bad practice.
Thanks!
This is certainly a rare occurrence, at least, in good quality code, because of the narrow case for which it's appropriate. What this basically does is a just-in-time initialization of a global state (to deliver some global functionality). A typical example of this is having a random number generator function that seeds the generator at the first call to it. Another typical use of this is a function that returns the instance of a singleton, initialized on the first call. But other use-case examples are few and far between.
In general terms, global state is not desirable, and having objects that contain self-sufficient states is preferred (for modularity, etc.). But if you need global state (and sometimes you do), you have to implement it somehow. If you need any kind of non-trivial global state, then you should probably go with a singleton class, and one of the preferred ways to deliver that application-wide single instance is through a function that delivers a reference to a local static instance initialized on the first call. If the global state needed is a bit more trivial, then doing the scheme with the local static bool flag is certainly an acceptable way to do it. In other words, I see no fundamental problem with employing that method, but I would naturally question its motivations (requiring a global state) if presented with such code.
As is always the case for global data, multi-threading will cause some problems with a simplistic implementation like this one. Naive introductions of global state are never going to be inherently thread-safe, and this case is no exception, you'd have to take measures to address that specific problem. And that is part of the reasons why global states are not desirable.
The behaviour of static bool init into SomeClass::function could be achieved with a non-static member variable.
If there is an alternative to achieve the same behavior, then the two alternatives have to be judged on the technical issues (like thread-safety). But in this case, the required behavior is the questionable thing, more so than the implementation details, and the existence of alternative implementations doesn't change that.
Second, I don't see how you can replace a just-in-time initialization of a global state by anything that is based on a non-static data member (a static data member, maybe). And even if you can, it would be wasteful (require per-object storage for a one-time-per-program-execution thing), and on that ground alone, wouldn't make it a better alternative.
Other functions in SomeClass couldn't check the static bool init value because it's visibility is limited to the void SomeClass::function() scope.
I would generally put that in the "Pro" column (as in Pro/Con). This is a good thing. This is information hiding or encapsulation. If you can hide away things that shouldn't be a concern to others, then great! But if there are other functions that would need to know that the global state has already been initialized or not, then you probably need something more along the lines of a singleton class.
The static variables aren't OOPish because they define a global state instead of a object state.
OOPish or not, who cares? But yes, the global state is the concern here. Not so much the use of a local static variable to implement its initialization. Global states, especially mutable global states, are bad in general and should never be abused. They hinder modularity (modules are less self-sufficient if they rely on global states), they introduce multi-threading concerns since they are inherently shared data, they make any function that use them non-reentrant (non-pure), they make debugging difficult, etc... the list goes on. But most of these issues are not tied to how you implement it. On the other hand, using a local static variable is a good way to solve the static-initialization-order-fiasco, so, they are good for that reason, one less problem to worry about when introducing a (well-justified) global state into your code.
Think multi-threading. This type of code is problematic when function() can be called concurrently by multiple threads. Without locking, you're open to race conditions; with locking, concurrency can suffer for no real gain.
Global state is probably the worst problem here. Other functions don't have to be concerned with it, so it's not an issue. The fact that it can be achieved without static variable essentially means you made some form of a singleton. Which of course introduces all problems that singleton has, like being totally unsuitable for multithreaded environment, for one.
Adding to what others said, you can't have multiple objects of this class at the same time, or at least would they not behave as expected. The first instance would set the static variable and do the initialization. The ones created later though would not have their own version of init but share it with all other instances. Since the first instance set it to true, all following won't do any initialization, which is most probably not what you want.
I'm wondering about this. I've heard that global variables are bad, that they hurt the maintainability, usability, reusability, etc. of the code. But in this case, what can I do otherwise? Namely, I have a "pseudo-random number generator" (PRNG) and as one may know, they involve an internal state that changes every time new random numbers are generated. But this seems like the kind of thing that needs to be a global! Or a "static" member of an RNG class, but that's essentially a global! And globals are bad!
So, what can I do? The obvious thing is to have something like this (really stripped down):
class RNG {
private:
StateType state; // this is the thing one may be tempted
// to make "static", which ruins the
// whole idea
public:
RNG(); // constructor seeds the RNG
~RNG();
int generateRandomInt();
};
But we need to seed that good, if we're going to create an instance of this every time we need a random number in some function or class. Using the clock may not work, since what if two instances of type "RNG" are created too close together? Then they get the same seed and produce the same random sequence. Bad.
We could also create one master RNG object and pass it around with pointers (instead of making it global, which would put us back on square 1), so that classes that need random numbers get a pointer to the RNG object in them. But then I run into a problem involving save/load of these objects to/from disk -- we can't just "save the RNG" for each instance, since we have only one RNG object. We'd have to instead pass an RNG into the load routines, which might give those routines different argument lists than for other objects that don't use the RNG. This would be a problem if, e.g. we wanted to use a common "Saveable" base class for everything that we can load/save. So, what to do? Eliminate the common "Saveable" base and just adopt a convention for how the load/save routines are to be made (but isn't that bad in and of itself? Oy!)?
What is the best solution to this that avoids the hostile-to-maintainability problems of globals yet also does not run into these new problems?
Or is it in fact okay to use a global here, as after all, that's how the "rand()" builtin works anyway? But then I hear that little thing in the back of my mind saying "but... but but but, globals are bad! Bad!" And from what I've read, there seem to be fairly good reasons to think them bad. But it seems like avoiding them creates new kinds of difficulties, like this one. It certainly seems harder to avoid globals than avoid "goto"s, for example.
There's some merit to your reluctance. You may want to substitute another generator for testing for example, that spits out a deterministic sequence that contains some edge cases.
Dependency Injection is one popular method for avoiding globals.
A random number generator is one of those things that is more OK to be global. You can think of it as:
-A RandomNumberFactory, a design pattern that uses a global factory, and it builds random numbers for you. The factory is of course constant semantically (in C++ you might use the keyword "mutable" internally, if that means anything to you.)
-A global constant (global constants are ok, right?) that gives you read-only access to the global constant randomNumber. randomNumber just happens to be non-deterministic, but it's constant in that of course no application is going to write to it.
-And besides, what's the worst that could happen? In a multithreaded application your RNG will yield non-deterministic behavior? Gasp. As #Mark Ransom pointed out above, yes that is actually a drawback as it makes testing harder. If this is a concern to you, you might consider a design pattern that writes this out.
It sometimes makes sense to use globals. No one can categorically say your code should not have any global variables, period.
What you do need is to be aware of the issues that can arise from global variables. If your application's logic needs global variables and it is possible for it to be called from a multi-threaded environment, then there is nothing inherently wrong with that, but you must take care to use locking, mutexes, and/or atomic reads/writes to ensure correct behavior.
I think it's best if I describe the situation using a code example:
int MyFuncA()
{
MyClass someInstance;
//<Work with and fill someInstance...>
MyFuncB( &someInstance )
}
int MyFuncB( MyClass* instance )
{
//Do anything you could imagine with instance, *except*:
//* Allowing references to it or any of it's data members to escape this function
//* Freeing anything the class will free in it's destructor, including itself
instance->DoThis();
instance->ModifyThat();
}
And here come my straightforward questions:
Is the above concept guranteed, by C and C++ standards, to work as expected? Why (not)?
Is this considered doing this, sparingly and with care, bad practice?
Is the above concept guranteed, by C and C++ standards, to work as expected? Why (not)?
Yes, it will work as expected. someInstance is available through the scope of MyFuncA. The call to MyFuncB is within that scope.
Is this considered doing this, sparingly and with care, bad practice?
Don't see why.
I don't see any problem in actually using the pointer you were passed to call functions on the object. As long as you call public methods of MyClass, everything remains valid C/C++.
The actual instance you create at the beginning of MyFuncA() will get destroyed at the end of MyFuncA(), and you are guaranteed that the instance will remain valid for the whole execution of MyFuncB() because someInstance is still valid in the scope of MyFuncA().
Yes it will work. It does not matter if the pointer you pass into MyFuncB is on the stack or on the heap (in this specific case).
In regards for the bad practice part you can probably argue both ways. In general it's bad I think because if for any reason any object which is living outside of MyFuncA gets hold of the object reference then it will die a horrible death later on and cause sometime very hard to track bugs. It rewally depends how extensive the usage of the object becomes in MyFuncB. Especially when it starts involving another 3rd class it can get messy.
Others have answered the basic question, with "yeah, that's legal". And in the absence of greater architecture it is hard to call it good or bad practice. But I'll try and wax philosophical on the broader question you seem to be picking up about pointers, object lifetimes, and expectations across function calls...
In the C++ language, there's no built-in way to pass a pointer to a function and "enforce" that it won't stow that away after the call is complete. And since C++ pointers are "weak references" by default, the objects pointed to may disappear out from under someone you pass it to.
But explicitly weak pointer abstractions do exist, for instance in Qt:
http://doc.qt.nokia.com/latest/qweakpointer.html
These are designed to specifically encode the "paranoia" to the recipient that the object it is holding onto can disappear out from under it. Anyone dereferencing one sort of realizes something is up, and they have to take the proper cautions under the design contract.
Additionally, abstractions like shared pointer exist which signal a different understanding to the recipient. Passing them one of those gives them the right to keep the object alive as long as they want, giving you something like garbage collection:
http://doc.qt.nokia.com/4.7-snapshot/qsharedpointer.html
These are only some options. But in the most general sense, if you come up with any interesting invariant for the lifetimes of your object...consider not passing raw pointers. Instead pass some pointer-wrapping class that embodies and documents the rules of the "game" in your architecture.
(One of major the reasons to use C++ instead of other languages is the wealth of tools you have to do cool things like that, without too much runtime cost!)
i don't think there should be any problem with that barring, as you say, something that frees the object, or otherwise trashes its state. i think whatever unexpected things happen would not have anything to do with using the class this way. (nothing in life is guaranteed of course, but classes are intended to be passed around and operated on, whether it's a local variable or otherwise i do not believe is relevant.)
the one thing you would not be able to do is keep a reference to the class after it goes out of scope when MyFuncA() returns, but that's just the nature of the scoping rules.
The constructors of globally declared classes are invoked before main is entered. While this can be confusing to a new reader of the code because it is done so infrequently, is it necessarily a bad idea?
It's not necessarily a bad idea, but usually, yes.
First, it's global data, and globals are usually a bad thing.
The more global state you have, the harder it becomes to reason about your program.
Second, C++ doesn't guarantee intialization order of static objects defined in different translation units (.cpp files) -- so if they depend on one another, you might be in trouble.
Yes, this is bad. Since you will have no way to catch exceptions and deal with them, the default handler will be used. In C++ that means calling terminate...
Example: contents a.cpp
#include <stdexcept>
int f() { throw std::runtime_error("boom"); return 42; }
int i = f();
int main(int argc, char* argv[])
{
return 0;
}
Output of : g++ a.cpp && ./a.out
terminate called after throwing an instance of 'std::runtime_error'
what(): boom
Aborted (core dumped)
You can try add a try ... catch in your main, that won't help.
Edit: Jalf's points are valid too. Listen to his advice.
In addition to being of questionable form - It will not be portable to some platforms.
As you point out, it is allowed. In the last company I worked at, when such a situation would arise, we made it policy to add an appropriate comment to main() to indicate for which variables this applied to. If you have a bad situation, try to make the best of it.
Using global/static objects with non-trivial constructors and destructors is awful. I saw enough huge software projects that found themselves in a catastrophe because of an uncontrolled use of global/static objects and singletones.
The problem is not the fact that it's the code that is run outside the main. It's that those objects are constructed and destroyed in an uncontrollable order.
In addition I believe it's a generally bad practice to use global variables anyway (even ordinary variables), with some exceptions.
Every piece of code should be run within a well-defined context, and all the variables should belong to it.
It's not bad form at all, and it's not confusing. Static initialization is a deliberate feature of the language. Use it when you need to. Same with globals. Use them when you need to. Like any feature, knowing when it is appropriate and knowing its limitations is part of being a strong programmer.
Bad form is restructuring an otherwise perfectly fine program just to avoid globals or static initialization.
I will have to go so far as to say it is bad form for non-PODs, especially if you are working in a team primarily because of initialization order problems that can easily arise from this.
// the following invokes undefined behavior.
static bool success=cout<<"hello world\n";
People generally don't write code like above, but consider if success was initialized to the return value of another function. Now anyone tempted to use cout or cerr or any other global object in that function has invoked the same undefined behavior.
For user-defined types with constructors and destructors, consider the alternative method where access is initialization:
static Foo& safe_static()
{
static Foo f;
return f;
}
Unfortunately this also has problems with thread safety so a lock mechanism of some sort is required for the construction of 'f' if you are accessing safe_static concurrently.
That said, I do think one should try to keep things simple. Unfortunately when it comes to user-defined objects defined at file scope, it's far too easy to run into undefined behavior. The little extra effort required to write something like safe_static above can prevent a lot of headaches.
Exceptions are another point. If your static objects throw out of their constructor, then you have no way to catch the exception. If you want your application to be really robust and even handle startup errors, you'll have to structure your code carefully (ex: have try/catch blocks in the constructors for the objects you create at file scope so that the exception is not thrown outside of the ctor and also avoid initializer lists that throw).
If you're working in a team, you might think to yourself, "Oh, I'm not accessing any other globals in my class, I might as well make it a simple global with internal linkage at file scope." That might true then, but before you know it, your co-worker adds another global variable and tries to access it from the constructor of your class. Suddenly you have undefined behavior which might not even show up as a problem on the main platform you are targeting only for your code to crash and do other odd things when you try to port your code elsewhere.
It's really not worth the potential headaches IMO, and it's a problem that's much easier to avoid than to fix.