• C

Declaring absolute globals in MSVC++6

I want to declare a variable (or two) that is ABSOLUTELY global.  By that I mean that any object within my project and program can access it.  I also may want to have a global object that contains stats for each instance of the program that is running.  Any help?

This question's for you Brain2000.  If you answer this Brain, I'll up the points to 200, but I'm setting it at 50 in case someone else answers it. :-)
LVL 1
mgonyeaAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

luisrCommented:
A global variable can be declared outside any function in a single source file like this:

int nAnyGlobal = 0;

and use it in any other source file like this:

extern int nAnyGlobal;

That is enough for a global variable that can be accessed only by the current instance.

If you want to access the same variable from any instance of your program, you have to put it in a shared section:

#pragma data_seg(".shared")
int nAnyGlobal = 0;  // Must be intialized
#pragma data_seg()

and your must add the following line to the .DEF file for your program:

SECTIONS .shared READ WRITE SHARED

and that's about it.

0
ZoppoCommented:
Hi mgonyea,

>> If you answer this Brain, I'll up the points to 200, but I'm setting it at 50 in case someone else answers it.

What kind of nepotism is this ???

If you want to give Brian2000 some points then ask a question 'Point for Brian2000' without a subject and the points you want to give him. Otherwise be fair and give all experts the same chance to earn points!

ZOPPO
0
mgonyeaAuthor Commented:
Relax zoppo, it was only a gag, an inside joke, per say.  But thanks for your input on the question.....
0
Powerful Yet Easy-to-Use Network Monitoring

Identify excessive bandwidth utilization or unexpected application traffic with SolarWinds Bandwidth Analyzer Pack.

ZoppoCommented:
yep, no problem, but you should use the lounge for jokes   ;)

ZOPPO
0
mgonyeaAuthor Commented:
Thanks luisr.  Works great.  I don't know where the lounge is :-(
0
mgonyeaAuthor Commented:
I'm bumping the points up to 200 for this one.  I have an object called CSession which hold statistics for the current session of the application.  I want all my dialogs to have access to this object so that it can run diagnostics based on the statistics.  Can you help?

Thanks a million....or 200 :-)
0
mgonyeaAuthor Commented:
Oh, I've tried using an "extern CSession __SessionStatistics", but when I go to access the object in another dialog, all char* members show up as garbage.
0
ZoppoCommented:
Do these dialogs belong to one process or to several processes?
0
mgonyeaAuthor Commented:
Also I've checked the addresses of the pointers of all the char* members in the CSession object, and they all point to the same address space!!  I fill the members in on construction of the object.  What have I done wrong!?!?!
0
mgonyeaAuthor Commented:
One process.
0
mgonyeaAuthor Commented:
One process.
0
ZoppoCommented:
We will need some relevant code to find it out I think ...
0
mgonyeaAuthor Commented:
Ok.  Here we go! :-) (I'll paste it for you)

Here's the object's construction code along with the LoadSettings function.

CSession::CSession()
{
 CommPort = LoadSettings("CommPort", 0);
 CommSettings = LoadSettings("CommSettings");

 DefaultHomePage = LoadSettings("DefaultHomePage");
 DefaultSearchPage = LoadSettings("DefaultSearchPage");
 MinimumCash = LoadSettings("MinimumCash", 0);
 NickelValue = LoadSettings("NickelValue", 0);

 RAS_Callback = LoadSettings("RAS_Callback");
 RAS_Domain = LoadSettings("RAS_Domain");
 RAS_Entry = LoadSettings("RAS_Entry");
 RAS_Password = LoadSettings("RAS_PAssword");
 RAS_Phone = LoadSettings("RAS_Phone");
 RAS_Username = LoadSettings("RAS_Username");

 SiteAddress = LoadSettings("SiteAddress");
 SiteID = LoadSettings("SiteID");
 SiteName = LoadSettings("SiteName");
 City = LoadSettings("City");
 Phone = LoadSettings("Phone");
 Fax = LoadSettings("Fax");
 Postal = LoadSettings("Postal");
 Country = LoadSettings("Country");
}


*************************************
** Loads registry values for program
*************************************
char* CSession::LoadSettings(char *szValue)
{
  CRegKey* Registry = new CRegKey();   // Create an instance of the CRegKey object
  long reg_mod_result;  // Result of  registry actions                                           Registry->Attach(HKEY_LOCAL_MACHINE);
      // Create / Open the settings

reg_mod_result = Registry->Create(HKEY_LOCAL_MACHINE, "Software\\NNKiosk\\Settings\\");

if (reg_mod_result != ERROR_SUCCESS) {
            AfxMessageBox("Couldn't open registry entry SOFTWARE\\NNKIOSK\\SETTINGS",0,0);
      }

  char buffer[80];
  unsigned long val_len = strlen(buffer);

  reg_mod_result = Registry->QueryValue(buffer, szValue, &val_len);
      
  if (reg_mod_result != ERROR_SUCCESS) {
            CString msg = "Couldn't retrieve registry value for ";
            msg += szValue;
            AfxMessageBox(msg,0,0);
      }

  char *ret_str = buffer;

  Registry->Close();
  return ret_str;
}

.....................
Now later on within the dialog box I have this function...

void AdCoreRemaining::RefreshSettings()
{
 extern CSession Stats;

 m_comm_port = Stats.CommPort;
 m_comm_settings = Stats.CommSettings;
 m_def_homepage = Stats.DefaultHomePage;
 m_def_searchpage = Stats.DefaultSearchPage;
 m_min_cash = Stats.MinimumCash;
 m_nickel = Stats.NickelValue;
 m_ras_entry = Stats.RAS_Entry;
 m_ras_password = Stats.RAS_Password;
 m_ras_phone = Stats.RAS_Phone;
 m_ras_username = Stats.RAS_Username;
 m_site_address = Stats.SiteAddress;
 m_site_fax = Stats.Fax;
 m_site_id = Stats.SiteID;
 m_site_name = Stats.SiteName;
 m_site_phone = Stats.Phone;
}
0
mgonyeaAuthor Commented:
One more thing..in the CoreBuild.cpp file, I have this declaration (outside of the CoreBuildApp object)

CSession Stats;
0
mgonyeaAuthor Commented:
Also, here's the class definition of CSession:

// Session.h: interface for the CSession class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_SESSION_H__5BA2B4E6_CF41_11D3_B3E6_0080C8F96AC1__INCLUDED_)
#define AFX_SESSION_H__5BA2B4E6_CF41_11D3_B3E6_0080C8F96AC1__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CSession : public CObject  
{
public:
      void SetProperty(int nPropSet, char *cVal = "", int nVal = 0);
      void SaveSettings_S(char *szValueName, char *szValue);
      void SaveSettings_I(char *szValueName, double dwVal);
      char* LoadSettings(char *szValue);
      int   LoadSettings(char *szValue, int AFlag);

      CSession();
      virtual ~CSession();

      char *DefaultHomePage;
      char *DefaultSearchPage;

      int CommPort;
      char *CommSettings;

      char *RAS_Entry;
      char *RAS_Phone;
      char *RAS_Callback;
      char *RAS_Username;
      char *RAS_Password;
      char *RAS_Domain;

      int NickelValue;
      int MinimumCash;
      
      char *SiteID;
      char *SiteName;
      char *SiteAddress;
      char *City;
      char *Country;
      char *Postal;
      char *Phone;
      char *Fax;

protected:

};

#endif // !defined(AFX_SESSION_H__5BA2B4E6_CF41_11D3_B3E6_0080C8F96AC1__INCLUDED_)
0
Brain2000Commented:
Hi mgonyea, I missed the bandwagon on this one :)

I know what the problem is.  The actual structure itself is put into shared memory.  However, when you fill in the pointers, that memory is NOT globally identified.  Since every process has it's own virtual memory map, address 0x100000 inside one process could point to something different than 0x100000 in another process.  In your LoadSettings(...) function, you allocate 80 bytes on the stack.

char buffer[80];

Keep in mind that this is very dangerous to store this pointer because after you return from your function, this stack memory is returned!  Technically, you could get an Access Violation error.

Declare a series of buffers (one per setting) globally, and wrap them in the #pragma data_seg() parameter.  For example:

#pragma data_seg(".shrared")
char buffer[20][80];
#pragma data_seg()

Also,

char buffer[80];
unsigned long val_len = strlen(buffer);

can be dangerous.  buffer[80] has not yet been filled in, and strlen() goes through counting characters until it hits a NULL.  This can also cause an Access Violation.  Try using sizeof(...) instead:

char buffer[80];
unsigned long val_len = sizeof(buffer);

But you're not going to do this anyways, because we've thrown buffer[80] out.  You're going to need a second parameter in your LoadSettings(...) function to determine which buffer to use.  Thus, you get the following code:


#define NUM_BUFFS
#define BUFFER_SIZE

#pragma data_seg(".shrared")
char buffer[NUM_BUFFS][BUFFER_SIZE];
#pragma data_seg()

CSession::CSession()
{
 CommPort = LoadSettings("CommPort", buffer[0]);
 CommSettings = LoadSettings("CommSettings",buffer[1]);

 DefaultHomePage = LoadSettings("DefaultHomePage",buffer[2]);
 DefaultSearchPage = LoadSettings("DefaultSearchPage",buffer[3]);
 MinimumCash = LoadSettings("MinimumCash",buffer[4]);
 NickelValue = LoadSettings("NickelValue",buffer[5]);

 RAS_Callback = LoadSettings("RAS_Callback",buffer[6]);
 RAS_Domain = LoadSettings("RAS_Domain",buffer[7]);
 RAS_Entry = LoadSettings("RAS_Entry",buffer[8]);
 RAS_Password = LoadSettings("RAS_PAssword",buffer[9]);
 RAS_Phone = LoadSettings("RAS_Phone",buffer[10]);
 RAS_Username = LoadSettings("RAS_Username",buffer[11]);

 SiteAddress = LoadSettings("SiteAddress",buffer[12]);
 SiteID = LoadSettings("SiteID",buffer[13]);
 SiteName = LoadSettings("SiteName",buffer[14]);
 City = LoadSettings("City",buffer[15]);
 Phone = LoadSettings("Phone",buffer[16]);
 Fax = LoadSettings("Fax",buffer[17]);
 Postal = LoadSettings("Postal",buffer[18]);
 Country = LoadSettings("Country",buffer[19]);
}


*************************************
** Loads registry values for program
*************************************
char* CSession::LoadSettings(char *szValue,char *buffer)
{
  CRegKey* Registry = new CRegKey();   // Create an instance of the CRegKey object
  long reg_mod_result;  // Result of  registry actions Registry->Attach(HKEY_LOCAL_MACHINE);
// Create / Open the settings

reg_mod_result = Registry->Create(HKEY_LOCAL_MACHINE, "Software\\NNKiosk\\Settings\\");

if (reg_mod_result != ERROR_SUCCESS) {
AfxMessageBox("Couldn't open registry entry SOFTWARE\\NNKIOSK\\SETTINGS",0,0);
}

  unsigned long val_len = BUFFER_SIZE;

  reg_mod_result = Registry->QueryValue(buffer, szValue, &val_len);

  if (reg_mod_result != ERROR_SUCCESS) {
CString msg = "Couldn't retrieve registry value for ";
msg += szValue;
AfxMessageBox(msg,0,0);
}

  Registry->Close();
  return buffer;
}
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
mgonyeaAuthor Commented:
Thanks !  Works like a charm!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.