[GiNaC-list] Include Guards
Sheplyakov Alexei
varg at theor.jinr.ru
Thu Jan 20 10:10:30 CET 2005
On Wed, Jan 19, 2005 at 03:55:19PM -0600, Jason Dusek wrote:
> In the FAQ, they discuss a problem with multiple inclusions of a
> header where global symbols are defined:
The problem has NOTHING to do with multiple inclusions of a
header. The actual problem is declaration of global variables
in different compilation units by inclusion a _single_ header
file, like this:
// file bogus.h
#ifndef VARGS_BOGUS_H
#define VARGS_BOGUS_H
#include <ginac/ginac.h>
const GiNaC::symbol x("x");
#endif
// file fun1.cpp
#include <ginac/ginac.h>
#include "bogus.h"
const GiNaC::ex fun1() { return x; }
// file fun2.cpp
#include <ginac/ginac.h>
#include "bogus.h"
const GiNaC::ex fun2() { return x; }
// file main.cpp
#include <iostream>
#include <ginac/ginac.h>
using namespace std;
using namespace GiNaC;
extern const ex fun1();
extern const ex fun2();
int main(int argc, char* argv)
{
ex bogus = fun1() - fun2();
// print expression as a tree
cout << tree << bogus << endl;
return 0;
}
On my system, this program will print
add @0x805ef88, hash=0xb7e7ae1a, flags=0x3, nops=2
x (symbol) @0x805eda8, serial=2, hash=0x670d3697, flags=0xf, domain=0
1 (numeric) @0x804fde8, hash=0x160af41d, flags=0xf
-----
x (symbol) @0x805ed70, serial=1, hash=0x79ba0000, flags=0xf, domain=0
-1 (numeric) @0x804fc58, hash=0xd60af41d, flags=0xf
=====
So, `bogus' is _not_ zero, because there are two _different_ symbols
(with the same print-name x): one of them was defined in the file
fun1.cpp, another -- in fun2.cpp. Note, that in this example header
file "bogus.h" gets included only once.
> ================================================
> Q: I have various modules, some global variables and...
>
> A: ...and you are getting weird results with symbols not being
> identical? Imagine this situation: A file globals.h declares symbol
> x("x"). Two other modules #include "globals.h", do something with
> symbol x and return an expression ex containing the symbol to the
> caller (e.g. to main()). When the caller combines the two expressions
> there are really two different symbols both with the same print-name
> x. This may cause terms like x-x to stay around which will never be
> simplified to 0 because the system has no knowledge that the two
> symbols are supposed to be the same. How should it? After all the
> declarations really happend in different compilation units!
> ================================================
> Can include guards solve this problem?
No, they can't.
> Do I *have* to make that evil factory initializer thingy?
You might use something like
// file bogus.h
#ifndef VARGS_GLOBAL_X_H
#define VARGS_GLOBAL_X_H
#include <ginac/ginac.h>
extern GiNaC::symbol x;
#endif
// file bogus.cpp
#include <ginac/ginac.h>
#include "bogus.h"
using namespace GiNaC;
symbol x("x");
// file fun1.cpp
#include <ginac/ginac.h>
#include "bogus.h"
const GiNaC::ex fun1() { return x; }
// file fun2.cpp
#include <ginac/ginac.h>
#include "bogus.h"
const GiNaC::ex fun2() { return x; }
// file main.cpp
#include <iostream>
#include <ginac/ginac.h>
using namespace std;
using namespace GiNaC;
extern const ex fun1();
extern const ex fun2();
int main(int argc, char* argv)
{
ex bogus = fun1() - fun2();
// print expression as a tree
cout << tree << bogus << endl;
// will print zero
return 0;
}
But (IMHO) such a code is even more evil :)
Best regards,
Alexei.
More information about the GiNaC-list
mailing list