Will two symbols with the same name clash?

D

DeMarcus

Hi,

Will two symbols with the same name but in different .cpp files clash?
E.g.

file1.cpp

int varA;


file2.cpp

int varA;


Will varA clash during linking? Of course I can test it myself, but is
there a possibility that they are allowed to clash but the compiler
chooses one of them?

Sometimes I've seen compiler messages like: "multiple definitions of X,
ignoring the latter".


Thanks,
Daniel
 
D

DeMarcus

DeMarcus said:
Hi,

Will two symbols with the same name but in different .cpp files clash?
E.g.

file1.cpp

int varA;


file2.cpp

int varA;


Will varA clash during linking? Of course I can test it myself, but is
there a possibility that they are allowed to clash but the compiler
chooses one of them?

Sometimes I've seen compiler messages like: "multiple definitions of X,
ignoring the latter".


Thanks,
Daniel

Wait, I just came to think of that I have to declare them static!
I.e.

file1.cpp

static int varA;

file2.cpp

static int varA;


It was a long time since I used that. ;)
 
A

Alf P. Steinbach

* DeMarcus:
Hi,

Will two symbols with the same name but in different .cpp files clash?

Depends what you mean by "clash".

If the symbols have extern linkage then C++ generally does not support that.
It's called the "ODR", "One Definition Rule". But a linker may not necessarily
detect the clash -- e.g. 'int a[5]' one place and 'int* a' another place.

There are some execptions, where you are allowed multiple definitions of extern
linkage things.

The most important is "inline" routines.

A similar exception is there for static lifetime data in templates.

E.g.

file1.cpp

int varA;


file2.cpp

int varA;


Will varA clash during linking?

Depends on the linker.

But the code above is not well-defined C++.

Of course I can test it myself, but is
there a possibility that they are allowed to clash but the compiler
chooses one of them?

No, not with the example above.

You can do that via the exception for templates mentioned above.

E.g., in each compilation unit, ...

template< class Dummy >
struct Var_ { static int a; };

template< class Dummy >
int Var_<Dummy>::a = 0;

typedef Var_<void> Var;

.... then use 'Var::a'.

Sometimes I've seen compiler messages like: "multiple definitions of X,
ignoring the latter".

That sounds like you're in violation of C++ rules.


Cheers & hth.,

- Alf
 
D

DeMarcus

Depends on the linker.

But the code above is not well-defined C++.

If I define the variables like this

file1.cpp
static int varA;

file2.cpp
static int varA;

Am I allowed to send either varA pointer to other places in the application?
 
P

Paul Bibbings

DeMarcus said:
Wait, I just came to think of that I have to declare them static!
I.e.

file1.cpp

static int varA;

file2.cpp

static int varA;


It was a long time since I used that. ;)

This particular use of the static keyword is deprecated in C++, IIRC.
To ensure that your two variables are not visible outside the
translation unit they are required in, use un-named namespaces:

// file1.cpp

namespace {
int varA;
}


// file2.cpp
namespace {
int varA;
}

Regards

Paul Bibbings
 
P

Paul Bibbings

DeMarcus said:
If I define the variables like this

file1.cpp
static int varA;

file2.cpp
static int varA;

Am I allowed to send either varA pointer to other places in the
application?

Are you able to say a little more about what you are trying to achieve?
With the little information we have, it strikes me, at least, as a
little convoluted. Your question began with name clashing, then sought
a method to make your same-named variables TU-local, and now you are
asking how you can refer to these same-named variables outside of the TU
they're defined in.

Questions to be asked include, in the first instance, "Why are your
variables named the same?" "What application-wide visibility do you want
for these variables?" Then you might want to ask yourself to what
extent your answers to these questions conflict.

Regards

Paul Bibbings
 
A

Alf P. Steinbach

* DeMarcus:
If I define the variables like this

file1.cpp
static int varA;

file2.cpp
static int varA;

Am I allowed to send either varA pointer to other places in the
application?

Yes, but keep in mind that here they're two distinct variables.


Cheers & hth.,

- Alf
 
D

DeMarcus

Paul said:
Are you able to say a little more about what you are trying to achieve?
With the little information we have, it strikes me, at least, as a
little convoluted. Your question began with name clashing, then sought
a method to make your same-named variables TU-local, and now you are
asking how you can refer to these same-named variables outside of the TU
they're defined in.

Questions to be asked include, in the first instance, "Why are your
variables named the same?" "What application-wide visibility do you want
for these variables?" Then you might want to ask yourself to what
extent your answers to these questions conflict.

I want to achieve the following.

file_class.cpp
const MessageClass ERROR( "Could not find file" );

class FileClass
{
public:
FileClass()
{
GlobalRegister::register( &ERROR );
}

void open( string s )
{
if( /* Error when opening file */ )
std::cerr << ERROR << std::endl;
}
};

calculation_class.cpp
const MessageClass ERROR( "Could not calculate" );

class CalculationClass
{
public:
CalculationClass()
{
GlobalRegister::register( &ERROR );
}

void calculate()
{
if( /* Error during calculation */ )
std::cerr << ERROR << std::endl;
}
};


I want to allow any file be able to use the symbol ERROR but at the same
time they shall be able to register the pointer to that variable without
clashing with other variables with the same symbol name.
 
D

DeMarcus

Paul said:
This particular use of the static keyword is deprecated in C++, IIRC.
To ensure that your two variables are not visible outside the
translation unit they are required in, use un-named namespaces:

// file1.cpp

namespace {
int varA;
}


// file2.cpp
namespace {
int varA;
}

Regards

Paul Bibbings

Thanks!!!
 
D

DeMarcus

Victor said:
What does that do?

It registers the ERROR MessageClass to a global register that keeps
track of all messages to give them correct language.

Actually the MessageClass looks more like this.

const MessageClass ERROR( "Could_not_find_file_id" );

where ERROR when used picks up correct language string.
What does that do?


Why? What for?


What does registering have to do with compilation? Are you confusing
run-time behavior (of your system) with the behavior of the compiler
(who determines and reports "name clashes")?

I want to be able to use the same symbols (here symbol ERROR) in
different places. The symbols then may clash in link-time (unless I put
them in different namespaces as suggested), however, each and every
MessageClass are registered in a global register where the language can
be changed.
 
D

DeMarcus

Victor said:
I suppose it pre-loads the translations from some repository (like
Resources on Windows), am I close?

Yes, all IDs are language-configured in text files.
OK, so the registration part of your system only cares about the *value*
of the string, not the actual address. Does it store a copy of it? Or
do you make your registration store the address of 'ERROR'? Not that
it's important, really... It should work either way.

My question was mostly to ensure that your 'register' does not try to
use the name of the variable ("ERROR") in any way. Of course, the use
of '&' is somewhat hinting that 'register' doesn't care about the
variable linked to the object whose address you're passing to it...

Well, the MessageClass has some functions like
const std::string& getID() const;
const std::string& getDefaultMessage() const;

One call to the global register could be:

globalRegister.printAllIDs();

That should be ok, right?
}
[...]

I want to allow any file be able to use the symbol ERROR but at the
same time they shall be able to register the pointer to that variable

Why? What for?

without
clashing with other variables with the same symbol name.

What does registering have to do with compilation? Are you confusing
run-time behavior (of your system) with the behavior of the compiler
(who determines and reports "name clashes")?

I want to be able to use the same symbols (here symbol ERROR) in
different places.

OK. Judging from the code you posted so far, there should be no
problem. Of course, you (hopefully) already found that if you make the
object 'const' you don't have that problem because a const object has
internal linkage by default. If you don't declare your object 'const',
it has external linkage, and without 'static' (which forces internal
linkage) or placing it in an unnamed namespace (which changes the name
of the var so it becomes inaccessible from other TUs) you will get
problems with the linker.

Aha, does this mean that as long as I declare them const, I don't need
the unnamed namespace? I.e. they will never be accessible or cause name
clashes outside the file (TU) they're compiled in?
Since those instances of 'MessageClass' all have their own storage,
their addresses are unique, and the "global register" should be able to
distinguish between two objects like that. Beware of address problems
when accessing objects across DLL boundaries (although this is quite
OS-specific), like defining the object in one DLL and using its address
in another.

This is a hard one. Is there a way to be totally sure it will work? I've
used the flag -fPIC before. Is that a guarantee?
 
D

DeMarcus

Pete said:
There's a separate issue here: "register" is a keyword. You can't use it
as an identifier.

Actually it's called something like

MessageSet::addMessage( &ERROR );
 
P

Paul Bibbings

DeMarcus said:
I want to achieve the following.

file_class.cpp
const MessageClass ERROR( "Could not find file" );

class FileClass
{
public:
FileClass()
{
GlobalRegister::register( &ERROR );
}

void open( string s )
{
if( /* Error when opening file */ )
std::cerr << ERROR << std::endl;
}
};

calculation_class.cpp
const MessageClass ERROR( "Could not calculate" );

class CalculationClass
{
public:
CalculationClass()
{
GlobalRegister::register( &ERROR );
}

void calculate()
{
if( /* Error during calculation */ )
std::cerr << ERROR << std::endl;
}
};


I want to allow any file be able to use the symbol ERROR but at the
same time they shall be able to register the pointer to that variable
without clashing with other variables with the same symbol name.

I have looked over the skeleton code that you have provided here and,
rather than it assisting me in thinking about how to best get around the
problems of multiply-defined ERROR instances, I cannot escape feeling
uneasy about the whole design. I am wondering if the very appearance of
the specific problems that you are facing here are not symptomatic of a
design that is otherwise flawed at a very fundamental level. Specific
questions that jump to mind without resolution (for me) and which lead
me to this through include the following:

1. What is the necessity in the first place of instantiating an
instance of an error message and then `registering' it by address?
Why is it not the responsibility of the GlobalRegister itself to
manage its own error messages - i.e., /contain/ them?

2. Why do you give the responsibility to each specific class -
FileClass, CalculationClass - for registering their respective error
messages? Why isn't the initialization of all such error messages
achieved at a single point of initialization at program startup?

I ask this, as it derives from the next question:
3. Why is it that each ERROR gets registered *every* time that an
instance of the relevant class is instantiated when all the
registration achieves is to add the *same* address to the *same*
object to the registry over and over again? Essentially, on
attempting to open 100 files or perform 1000 calculations, what is
the purpose of the registry holding 100/1000 pointers to the same
single ERROR instance?

4. What is the purpose of registering in the first place, when you
do not then make use of the registry to retrieve the appropriate
error message in, for example, FileClass::eek:pen(string) and
CalculationClass::calculate()? Instead, you short circuit the
registry (in effect) and make use of the TU-local ERROR instance
directly (and I would suggest that it is only because of this
avoidance of the registry at this point that you suppose that the
presence of these TU-local ERROR instances contributes to your
design.)

Without, clearly, having a full sense of the wider program this code
applies to - for instance, I only have a vague idea from other posts of
yours what the registry's purpose is - I nevertheless feel that some
other design effort is required in order to centralise responsibilities
where they belong and, in particular, to give to the registry full
handling of the objects that you are registering with it; then, it is
for the program code to *use* that registry.

With a design broadly along these lines you will find there shall be no
need for any ERROR objects outside of the registry, no necessity of them
being similarly named and requiring special handling to avoid name
clashes, and that the system as a whole will be better balanced in terms
of design. It will also be more readily extensible.

As an idea, I would suggest that you at least consider the following as
alternatives to your present design:

1. Let your `registry' be a full-fledged registry in the sense that
it alone is responsible for managing the objects registered with it
(i.e., let them not have an existence /outside/ of the registry
itself);

2. Let all interaction with the registered objects (error messages
here) be through the interface of the registry;

3. Let all such objects required by your program be registered in a
single place during program startup, unless (which your example code
doesn't indicate is the case) the error messages contain more
detailed information about the /specific/ context in which a
particular error has occurred.

And finally, consider whether you need the registry at all. From other
posts I am gathering that it's purpose is to enable appropriate error
messages to be output in an appropriate language. Is this not the
domain of std::locale? Why not just have appropriate error messages
raised where required and have your MessageClass respond, in terms of
what it actually outputs, according to the locale of the program user.
Again, it's about responsibilities. It seems fair to argue that it is
the responsibility of a MessageClass to be locale aware, itself, in this
sense.

Regards

Paul Bibbings
 
O

osmium

Victor said:
Next standard should remove it, don't you think?

I think removing it would simply makes things worse. That would produce a
new and mostly unused dialect and a bunch of additional folklore to dig
through in, say, 2050. Old computer languages should be allowed to die a
peaceful death. I would put C++ near the top of that list.
 
D

DeMarcus

Paul said:
I have looked over the skeleton code that you have provided here and,
rather than it assisting me in thinking about how to best get around the
problems of multiply-defined ERROR instances, I cannot escape feeling
uneasy about the whole design. I am wondering if the very appearance of
the specific problems that you are facing here are not symptomatic of a
design that is otherwise flawed at a very fundamental level. Specific
questions that jump to mind without resolution (for me) and which lead
me to this through include the following:

1. What is the necessity in the first place of instantiating an
instance of an error message and then `registering' it by address?
Why is it not the responsibility of the GlobalRegister itself to
manage its own error messages - i.e., /contain/ them?

Thanks for your thorough examination. It's much appreciated.

I've been turning this idea upside down, inside out several times to
really make sure I'm doing the right thing. To be able to provide
language neutral output, the actual point where the output is done
cannot use plain text but must provide an ID to text representing the
output. I.e.

// Not language neutral
output->print( "Error. Couldn't find file." );

// Language neutral using a string ID.
output->print( "file_not_found_error" );

Now, using a string as ID has two problems.
1. There is no compile-time check that the message exists.
2. Decentralization of the ID spreading concrete IDs all over the code.

After lots of investigation I took the design decision to use a constant
class as ID.

// Language neutral using a constant class ID.
output->print( FILE_NOT_FOUND_ERROR );

This solves some problems.
1. Possible misspelling of an ID. The compiler will catch a misspelled
constant.
2. The programmer is now forced to create the message before any output
can be done. With a plain string as ID the creation of the message
can be postponed and forgotten.
3. Name clashes of the ID is easier to resolve. A constant as ID can
contain not only the message ID string but also a category and a
default message, e.g.
const MessageClass FILE_NOT_FOUND_ERROR(
"XYZ_Inc_plugin",
"file_not_found_error",
"Error. Couldn't find file." );
All this can be centrally maintained by inheritance of
XYZIncMessageClass.

2. Why do you give the responsibility to each specific class -
FileClass, CalculationClass - for registering their respective error
messages? Why isn't the initialization of all such error messages
achieved at a single point of initialization at program startup?

You're completely right. I just put that in the constructor to put it
somewhere for the example. In the real design the registration is done
in the constructor of MessageClass; a so-called self-registration.

MessageClass
{
public:
MessageClass( string category, string id, string defaultMessage )
: category_(category), id_(id), defaultMessage_(defaultMessage)
{
MessageSet::addMessage( this );
}
};
I ask this, as it derives from the next question:
3. Why is it that each ERROR gets registered *every* time that an
instance of the relevant class is instantiated when all the
registration achieves is to add the *same* address to the *same*
object to the registry over and over again? Essentially, on
attempting to open 100 files or perform 1000 calculations, what is
the purpose of the registry holding 100/1000 pointers to the same
single ERROR instance?

You're right, see above.
4. What is the purpose of registering in the first place, when you
do not then make use of the registry to retrieve the appropriate
error message in, for example, FileClass::eek:pen(string) and
CalculationClass::calculate()? Instead, you short circuit the
registry (in effect) and make use of the TU-local ERROR instance
directly (and I would suggest that it is only because of this
avoidance of the registry at this point that you suppose that the
presence of these TU-local ERROR instances contributes to your
design.)

Sorry again, maybe I simplified the example too much. I have an own
class doing the lookup of the internationalized message and the prints
the output. E.g.

class FileClass
{
public:

void open( string s )
{
if( /* Error when opening file */ )
output->print( FILE_NOT_FOUND_ERROR );
}
};

In the output class it takes the category and id of the message, looks
up the correct message for current language in the global register and
prints it. If it for some reason can't find a translation in the
register it falls back on the default message which is English.

Without, clearly, having a full sense of the wider program this code
applies to - for instance, I only have a vague idea from other posts of
yours what the registry's purpose is - I nevertheless feel that some
other design effort is required in order to centralise responsibilities
where they belong and, in particular, to give to the registry full
handling of the objects that you are registering with it; then, it is
for the program code to *use* that registry.

With a design broadly along these lines you will find there shall be no
need for any ERROR objects outside of the registry, no necessity of them
being similarly named and requiring special handling to avoid name
clashes, and that the system as a whole will be better balanced in terms
of design. It will also be more readily extensible.

As an idea, I would suggest that you at least consider the following as
alternatives to your present design:

1. Let your `registry' be a full-fledged registry in the sense that
it alone is responsible for managing the objects registered with it
(i.e., let them not have an existence /outside/ of the registry
itself);

The design is built on self-registration, and I was partly inspired by
Jim Beveridge's article in Dr. Dobb's:
www.drdobbs.com/184410633
2. Let all interaction with the registered objects (error messages
here) be through the interface of the registry;

It is, but in a different way that one may be used to. I guess that you
propose something like.

std::cout << myReg->getMessage( "file_not_found" ) << std::endl;

I try to do as much lazy evaluation as possible so almost nothing is
evaluated out in the programmer's code but rather handled in
output->print()
that takes a pointer to the ID of the message.
3. Let all such objects required by your program be registered in a
single place during program startup, unless (which your example code
doesn't indicate is the case) the error messages contain more
detailed information about the /specific/ context in which a
particular error has occurred.

It's actually a mix of centralization and decentralization where in the
decentralization part one is able to provide messages in the same .cpp
file as they are used, but since they are just plain IDs and
self-registering the main work is centralized to one repository.
And finally, consider whether you need the registry at all. From other
posts I am gathering that it's purpose is to enable appropriate error
messages to be output in an appropriate language. Is this not the
domain of std::locale? Why not just have appropriate error messages
raised where required and have your MessageClass respond, in terms of
what it actually outputs, according to the locale of the program user.
Again, it's about responsibilities. It seems fair to argue that it is
the responsibility of a MessageClass to be locale aware, itself, in this
sense.

I'd like to use standardized tools but as far as I understand
std::locale is not that powerful when it comes to message strings. For
instance, as I understand, doing an output with variables is not
supported. E.g. print( "There are $1 plug-ins loaded.", nPlugins );
 
D

DeMarcus

Victor said:
DeMarcus said:
Victor said:
DeMarcus wrote:
Victor Bazarov wrote:
DeMarcus wrote:
[...]
I want to allow any file be able to use the symbol ERROR but at
the same time they shall be able to register the pointer to that
variable

Why? What for?

without
clashing with other variables with the same symbol name.

What does registering have to do with compilation? Are you
confusing run-time behavior (of your system) with the behavior of
the compiler (who determines and reports "name clashes")?


I want to be able to use the same symbols (here symbol ERROR) in
different places.

OK. Judging from the code you posted so far, there should be no
problem. Of course, you (hopefully) already found that if you make
the object 'const' you don't have that problem because a const object
has internal linkage by default. If you don't declare your object
'const', it has external linkage, and without 'static' (which forces
internal linkage) or placing it in an unnamed namespace (which
changes the name of the var so it becomes inaccessible from other
TUs) you will get problems with the linker.

Aha, does this mean that as long as I declare them const, I don't need
the unnamed namespace? I.e. they will never be accessible or cause
name clashes outside the file (TU) they're compiled in?

If your linker does not complain (which it shouldn't), then you're set.
This is a hard one. Is there a way to be totally sure it will work?
I've used the flag -fPIC before. Is that a guarantee?

I have no idea what you're talking about. Those things platform- and
compiler-specific. You need to consult the newsgroup dedicated to your
OS, most likely.

V

Ok, I'll check that up. Thanks!
 
Ö

Öö Tiib

I want to achieve the following.

file_class.cpp
const MessageClass ERROR( "Could not find file" );

class FileClass
{
public:
    FileClass()
    {
       GlobalRegister::register( &ERROR );
    }

    void open( string s )
    {
       if( /* Error when opening file */ )
          std::cerr << ERROR << std::endl;
    }

};

calculation_class.cpp
const MessageClass ERROR( "Could not calculate" );

class CalculationClass
{
public:
    CalculationClass()
    {
       GlobalRegister::register( &ERROR );
    }

    void calculate()
    {
       if( /* Error during calculation */ )
          std::cerr << ERROR << std::endl;
    }

};

I want to allow any file be able to use the symbol ERROR but at the same
time they shall be able to register the pointer to that variable without
clashing with other variables with the same symbol name.

If you run out of ideas or are stuck with something, then you can look
at how GNU gettext works (translation tool poedit). Also how QT
translations are made (translation tool qt-linguist). It feels that
you are perhaps inventing something similar.
 
D

DeMarcus

If you run out of ideas or are stuck with something, then you can look
at how GNU gettext works (translation tool poedit). Also how QT
translations are made (translation tool qt-linguist). It feels that
you are perhaps inventing something similar.

Yes, I will get some inspiration from there. For the frontend I will
probably use Qt, but I'm still working on the backend where I want to
avoid as much third party dependencies as possible. Right now it's only
boost.
 
Ö

Öö Tiib

Yes, I will get some inspiration from there. For the frontend I will
probably use Qt, but I'm still working on the backend where I want to
avoid as much third party dependencies as possible. Right now it's only
boost.

Yes, good goal. If you avoid application logic dealing with
interaction with user (i assume application logic is backend by you)
then you can keep it as not translated. For example throw exceptions
containing error codes, relevant data and English-only texts. Leave
human interaction entirely as responsibility of user interface (i
assume it is frontend by you). As result translations are user
interfaces responsibility and QT handles it quite well.

Showing raw exception or error texts to end user is dangerous because
people sometimes write odd texts when handling hard to reproduce
corner cases.

void foo( int param )
{
if ( !usualValue(param) )
{
throw OurUnexpected("how we got such param here?", param);
// TODO: figure it out
}

// ... usual logic
}

Such TODO-s will be often left as debt since thing works, unit test
runs (exception, like expected), testers did not discover case when
unusual value gets to foo, budget is used up and management pressures
it to market. Results are humorous at best when such exception text is
displayed to end user.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,740
Latest member
AdolphBig6

Latest Threads

Top