By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,931 Members | 1,566 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,931 IT Pros & Developers. It's quick & easy.

rules of extern

P: n/a
I have a few global variables in my app. They are defined in the main
application class file and declared (extern) in a header which can be
included by anyone who would want to use these variables.

Two of the globals are pointers which are initialized at runtime. The others
are classes whose values are initialized in the global space. When I had
just the pointers, I didn't need to include the extern header in the
defining class file. But now that I have the objects, I do. If I don't, ld
complains about undefined references.

Why is this?

It looks basically like this:

main.cpp

A *ptr;
B obj("string literal");

secondary.cpp

#include "externs.h"

void Secondary::method() {
cout << obj.toCharArr();
}

externs.h

class A;
class B;

extern A *ptr;
extern B obj;

Thanks,

--John Ratliff
Jul 26 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a

"John Ratliff" <so*****@microsoft.com> wrote in message
news:SKrFe.181020$x96.174068@attbi_s72...
I have a few global variables in my app. They are defined in the main
application class file and declared (extern) in a header which can be
included by anyone who would want to use these variables.

Two of the globals are pointers which are initialized at runtime. The
others are classes whose values are initialized in the global space. When
I had just the pointers, I didn't need to include the extern header in the
defining class file.
I don't understand. What's "the defining class file"?
But now that I have the objects, I do. If I don't, ld complains about
undefined references.

Why is this?

Any unit which references a variable must be able to "see" that variable
somehow. Below, secondary.cpp contains code which references obj, so obj
must be defined somewhere visible to secondary.cpp, which is what including
externs.h does for it. This minimal example doesn't show ptr being used
anywhere, so naturally it won't require externs.h. Perhaps your real code
does have ptr referenced there somewhere, but if it does, it has to define
ptr _someplace_ which is visible to the code. But without the real code,
I'd only be guessing.
It looks basically like this:

main.cpp

A *ptr;
B obj("string literal");

secondary.cpp

#include "externs.h"

void Secondary::method() {
cout << obj.toCharArr();
}

externs.h

class A;
class B;

extern A *ptr;
extern B obj;

Thanks,

--John Ratliff

Jul 26 '05 #2

P: n/a
Yeah, sorry for the not real code, but I can't seem to reduce the real code
to a small compilable problem. Let me try and rephrase.

In the file where the storage space for these globals is created, if I don't
also have the extern declarations, the linker will say my globals (the ones
that are not pointers) will say there are undefined references to these
variables. In other words, unless I have an extern declaration of these
variables (the ones that are not pointers), the linker will not export them
to the other modules. Yet, it exports the pointers with or without including
the extern declarations.

Is it a C++ requirement that I use an extern declaration if I want to export
these symbols? Are they limited to the module if I don't?

I guess maybe a better question might be, are variables declared at file
scope exported or not? Does the export require an extern declaration?

I read this in the C++ Faq Lite " (By the way, static data at file-scope is
now deprecated in C++: don't do that.) ". What does this mean? Is it saying
what I did was bad?

BidEuchreApp.cc (where storage space is defined for the globals)
------------------
#include "AppConstants.hh"

wxMutex *mutex;
wxCondition *cond;

const wxString APP_NAME(wxT(PACKAGE_NAME));
const wxString APP_VERSION(wxT(PACKAGE_VERSION));
const wxString APP_COPYRIGHT(wxT("Copyright (C) 2005 John David Ratliff"));
const wxString APP_URL(wxT("http://games.technoplaza.net/"));

BidEuchreApp::BidEuchreApp() {
mutex = new wxMutex();
cond = new wxCondition(*mutex);
}
------------------

AppConstants.hh
-------------------
class wxCondition;
class wxMutex;
class wxString;

extern const wxString APP_NAME;
extern const wxString APP_VERSION;
extern const wxString APP_COPYRIGHT;
extern const wxString APP_URL;
extern wxCondition *cond;
extern wxMutex *mutex;
---------------------------------

EuchreFrame.cc
-----------------------
#include "AppConstants.hh"

void EuchreFrame::helpAbout(wxCommandEvent& WXUNUSED(event)) {
wxString message = APP_NAME + wxT(' ') + APP_VERSION + wxT('\n') +
APP_COPYRIGHT + wxT('\n') + APP_URL;
wxString title = wxT("About ") + APP_NAME + wxT("...");

wxMessageBox(message, title, wxOK | wxICON_INFORMATION, this);
}
----------------------

Here is the actual code. I will post the entire compilable module if you
think it will help, but I have 30 some files and it requires wxWidgets 2.6
to compile. You can assume it does use cond and mutex somewhere, but not in
EuchreFrame.cc or BidEuchreApp.cc.

If you remove the include of AppConstants.hh in the BidEuchreApp.cc file,
you will get the following linker errors.

ui/EuchreFrame.o(.text+0x1266):C:/msys/1.0/home/jdratlif/bideuchre/source/ui/EuchreFrame.cc:77:
undefined reference to `APP_VERSION'
ui/EuchreFrame.o(.text+0x12b8):C:/msys/1.0/home/jdratlif/bideuchre/source/ui/EuchreFrame.cc:77:
undefined reference to `APP_COPYRIGHT'
ui/EuchreFrame.o(.text+0x130d):C:/msys/1.0/home/jdratlif/bideuchre/source/ui/EuchreFrame.cc:77:
undefined reference to `APP_URL'
ui/EuchreFrame.o(.text+0x13b5):C:/msys/1.0/home/jdratlif/bideuchre/source/ui/EuchreFrame.cc:78:
undefined reference to `APP_NAME'
collect2: ld returned 1 exit status

The question is, why does the linker find the cond and mutex variables, but
not the APP_XXX variables?

Game.cc
----------------------
void Game::setPause(bool paused) {
this->paused = paused;
cond->Signal();
}
----------------------

Just one of the places cond is used, and ld has no problem with
BidEuchreApp.hh not including AppConstants.hh.

Thanks,

--John Ratliff
Jul 26 '05 #3

P: n/a

"John Ratliff" <so*****@microsoft.com> wrote in message
news:CjzFe.183768$_o.148646@attbi_s71...
Yeah, sorry for the not real code, but I can't seem to reduce the real
code to a small compilable problem. Let me try and rephrase.

In the file where the storage space for these globals is created, if I
don't also have the extern declarations, the linker will say my globals
(the ones that are not pointers) will say there are undefined references
to these variables. In other words, unless I have an extern declaration of
these variables (the ones that are not pointers), the linker will not
export them to the other modules. Yet, it exports the pointers with or
without including the extern declarations.

Is it a C++ requirement that I use an extern declaration if I want to
export these symbols? Are they limited to the module if I don't?

The extern specifier tells the compiler that the symbol is defined
elsewhere, and the reference must be resolved at link time.
I guess maybe a better question might be, are variables declared at file
scope exported or not? Does the export require an extern declaration?

You don't "export" the symbol. You simply declare it as exterrn in any unit
that needs to see it but doesn't wish to directly include the file it's
declared in. In your case, you declare it extern in a header, and include
the header wherever it's needed. That's the correct way.
I read this in the C++ Faq Lite " (By the way, static data at file-scope
is now deprecated in C++: don't do that.) ". What does this mean? Is it
saying what I did was bad?

I see nothing declared as "static" here.
BidEuchreApp.cc (where storage space is defined for the globals)
------------------
#include "AppConstants.hh"

wxMutex *mutex;
wxCondition *cond;

const wxString APP_NAME(wxT(PACKAGE_NAME));
const wxString APP_VERSION(wxT(PACKAGE_VERSION));
const wxString APP_COPYRIGHT(wxT("Copyright (C) 2005 John David
Ratliff"));
const wxString APP_URL(wxT("http://games.technoplaza.net/"));

Those are your declarations (and definitions of the wxString variables).
BidEuchreApp::BidEuchreApp() {
mutex = new wxMutex();
cond = new wxCondition(*mutex);
}
Fine, because cond and mutex are declared above.
------------------

AppConstants.hh
-------------------
class wxCondition;
class wxMutex;
class wxString;

extern const wxString APP_NAME;
extern const wxString APP_VERSION;
extern const wxString APP_COPYRIGHT;
extern const wxString APP_URL;
extern wxCondition *cond;
extern wxMutex *mutex;
---------------------------------

EuchreFrame.cc
-----------------------
#include "AppConstants.hh"

void EuchreFrame::helpAbout(wxCommandEvent& WXUNUSED(event)) {
wxString message = APP_NAME + wxT(' ') + APP_VERSION + wxT('\n') +
APP_COPYRIGHT + wxT('\n') + APP_URL;
wxString title = wxT("About ") + APP_NAME + wxT("...");

wxMessageBox(message, title, wxOK | wxICON_INFORMATION, this);
}
----------------------

Here is the actual code. I will post the entire compilable module if you
think it will help, but I have 30 some files and it requires wxWidgets 2.6
to compile. You can assume it does use cond and mutex somewhere, but not
in EuchreFrame.cc or BidEuchreApp.cc.

If you remove the include of AppConstants.hh in the BidEuchreApp.cc file,
you will get the following linker errors.

I must assume that you mean the problem occurs if you remove the include
from EuchreFrame.cc, since that's what the errors refer to. And
EuchreFrame.cc needs to tell the compiler where those symbols are defined.
It does so (in this case) by including the header file which declares them
as extern (thereby putting it on the linker to resolve the extern
declarations).
ui/EuchreFrame.o(.text+0x1266):C:/msys/1.0/home/jdratlif/bideuchre/source/ui/EuchreFrame.cc:77:
undefined reference to `APP_VERSION'
ui/EuchreFrame.o(.text+0x12b8):C:/msys/1.0/home/jdratlif/bideuchre/source/ui/EuchreFrame.cc:77:
undefined reference to `APP_COPYRIGHT'
ui/EuchreFrame.o(.text+0x130d):C:/msys/1.0/home/jdratlif/bideuchre/source/ui/EuchreFrame.cc:77:
undefined reference to `APP_URL'
ui/EuchreFrame.o(.text+0x13b5):C:/msys/1.0/home/jdratlif/bideuchre/source/ui/EuchreFrame.cc:78:
undefined reference to `APP_NAME'
collect2: ld returned 1 exit status

The question is, why does the linker find the cond and mutex variables,
but not the APP_XXX variables?
It doesn't. Look again. The pointers are never referenced in
EuchreFrame.cc, which is where the errors occur.

Game.cc
----------------------
void Game::setPause(bool paused) {
this->paused = paused;
cond->Signal();
}
----------------------

Just one of the places cond is used, and ld has no problem with
BidEuchreApp.hh not including AppConstants.hh.


You don't show what's included by Game.cc (or what's included by what it
includes...). So I can't tell where it's seeing cond from, but trust me,
it's included somehow.

You don't show any code from BidEuchreApp.hh, so I can't comment on that
one. My guess is that neither mutex nor cond are referenced in that file.
They are referenced in BidEuchreApp.cc, but that's where they are declared,
so there's no problem there.

I think you're just confusing EuchreFrame.cc and BidEuchreApp.cc here. It
doesn't matter if the variable is a pointer or any otther kind of object..it
must either be declared in the file, declared in an included file (or a file
included by a file that's included, etc.), or declared as extern (and then
actually defined elsewhere).

-Howard
Jul 27 '05 #4

P: n/a
>>If you remove the include of AppConstants.hh in the BidEuchreApp.cc file,
you will get the following linker errors.
I must assume that you mean the problem occurs if you remove the include
from EuchreFrame.cc, since that's what the errors refer to. And
EuchreFrame.cc needs to tell the compiler where those symbols are defined.
It does so (in this case) by including the header file which declares them
as extern (thereby putting it on the linker to resolve the extern
declarations).


No, this is not what I mean. I am really and truly referring to
BidEuchreApp.cc. It does not make sense to me either. EuchreFrame.cc has
AppConstants.hh included at the top, before it uses the globals. If it
did not, wouldn't I get a compiler error and be unable to reach the link
stage?

This doesn't seem right, but is it possible the rules are different for
global objects than global pointers (or other primitives)? Is it
possible objects are static by default, and primitives are extern?

ui/EuchreFrame.o(.text+0x1266):C:/msys/1.0/home/jdratlif/bideuchre/source/ui/EuchreFrame.cc:77:
undefined reference to `APP_VERSION'
ui/EuchreFrame.o(.text+0x12b8):C:/msys/1.0/home/jdratlif/bideuchre/source/ui/EuchreFrame.cc:77:
undefined reference to `APP_COPYRIGHT'
ui/EuchreFrame.o(.text+0x130d):C:/msys/1.0/home/jdratlif/bideuchre/source/ui/EuchreFrame.cc:77:
undefined reference to `APP_URL'
ui/EuchreFrame.o(.text+0x13b5):C:/msys/1.0/home/jdratlif/bideuchre/source/ui/EuchreFrame.cc:78:
undefined reference to `APP_NAME'
collect2: ld returned 1 exit status

The question is, why does the linker find the cond and mutex variables,
but not the APP_XXX variables?

It doesn't. Look again. The pointers are never referenced in
EuchreFrame.cc, which is where the errors occur.


Yes it does. They are used in Game.cc, and Game.cc produces no errors. I
can even remove the use of the APP_XX constants from EuchreFrame and the
include from BidEuchreApp.cc and Game.cc will still be able to use the
cond and mutex.
Game.cc
----------------------
void Game::setPause(bool paused) {
this->paused = paused;
cond->Signal();
}
----------------------

Just one of the places cond is used, and ld has no problem with
BidEuchreApp.hh not including AppConstants.hh.
You don't show what's included by Game.cc (or what's included by what it
includes...). So I can't tell where it's seeing cond from, but trust me,
it's included somehow.


Game.cc includes AppConstants.hh. Sorry.

You don't show any code from BidEuchreApp.hh, so I can't comment on that
one. My guess is that neither mutex nor cond are referenced in that file.
They are referenced in BidEuchreApp.cc, but that's where they are declared,
so there's no problem there.
I meant BidEuchreApp.cc here. Apologies again. BidEuchreApp.hh is solely
a class def with no includes whatsoever.

I think you're just confusing EuchreFrame.cc and BidEuchreApp.cc here. It
doesn't matter if the variable is a pointer or any otther kind of object..it
must either be declared in the file, declared in an included file (or a file
included by a file that's included, etc.), or declared as extern (and then
actually defined elsewhere).


Thanks for all your time. I hope we're closer to solving this. Actually,
I don't care that I have to include the file in BidEuchreApp.cc where
they are defined. I just want to know why I do.

--John Ratliff
P.S. I don't know if it's helpful, but I posted the entire source at
http://www.technoplaza.net/temp/bideuchre-0.1.tar.bz2. Unless you have
wx 2.6, you won't be able to compile it though.
Jul 27 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.