Solved

Problem initializing (extern) array, C++, MFC

Posted on 2011-02-16
4
783 Views
Last Modified: 2012-05-11
Hi.
I have a problem initializing array..
Program compiles without any errors & warnings, but when it starts ASSERT failure occurs,
because array elements are <bad pointers>.
See some code snippets..
Any help would be highly appreciated!!
In one header, lets call it A.h is defined struct TranslationPair and this header is included in stdafx.h:
struct TranslationPair
{
	TranslationPair(LPCTSTR sk, LPCTSTR sv) : sKey(sk), sDefVal(sv)
	{ }

	TranslationPair(TranslationPair& tp) : sKey(tp.sKey), sDefVal(tp.sDefVal)
	{ }

	

	CString sKey;
	CString sDefVal;
};

Then in stdafx.cpp is defined (and initialized) array arUserPermissionsDescs:
const TranslationPair arUserLevels[SECURITY_MAX_PERMISSIONS] = 
{
	TranslationPair ( _T("A"), _T("A") ),
              TranslationPair ( _T("B"), _T("B") ),
};
Now in another file, lets call it B.h:
extern const TranslationPair arUserLevels[SECURITY_LEVELS_NR];
ASSERT occurs in one of the methods of class defined in B.h & B.cpp:
void B::func()
{
  CString s = _T("AA");
  s == arUserLevels[0].sKey; // ASSERT, aruserLevels[0] - bad pointer, probably, array not initialized.
}
Some info about application:
1) It's MFC application.
2) Call stack looks like:  __tmainCRTStartup()->....->constructor of CMyApp(which is derived from CWinApp)->constructor of class defined in B(i.e it's called from constructor of CMyApp) -> B::func()
3) That's all, any ideas

Open in new window

0
Comment
Question by:SpringMVC
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
4 Comments
 
LVL 31

Expert Comment

by:Zoppo
ID: 34908224
Hi SpringMVC,

I guess the problem is caused by the fact you try to access the array within your CWinApp-derived classes constructor (i.o.w. when 'theApp' is initialized).

In this case it's not granted that 'arUserLevels' is already initialized since both 'arUserLevels' and 'theApp' are global variables, so it's undefined which one is initialized first.

I think to get this working you should move the code which accesses 'arUserLevels' (so the code from the app's constructor which calls 'B::func') to anywhere else where you know everything global is initialized completeley, i.e. to your CWinApp-derived classes 'InitInstance' method.

Hope that helps,

ZOPPO
0
 

Author Comment

by:SpringMVC
ID: 34908518
Thanks for suggestion, probably, you are right.

But in past it was:
TCHAR *arUserLevels[MAX] =
{
  _T("Admin", _T("User"), _T("SuperUser")
};
and it worked!!
Now problem is, that class B has no default contructor, and the object of B is in CMyApp..
So if I put initializing of B in InitInstance, I will have to make a default constructor for B, which will break application's logic/structure/or whatever it is..
Any ideas, how can I make refactoring? :)

P.S By the way, sorry for English :)
0
 
LVL 31

Accepted Solution

by:
Zoppo earned 500 total points
ID: 34908652
IMO the shown code worked earlier but doesn't work anymore is that you exchanged const string literals with structs. With the new code the structs within 'arUserLevels' have to be initialized during startup in order to call every entry's constructor. With the 'old' code this wasn't needed since 'arUserLevels' contained simply const char pointers.

I think there may be several ways to workaround this. One which maybe suitable could be to move the array to a static member function. For example if CMyApp is the CWinApp-derived class this could look like this:

// myapp.h

#define SECURITY_MAX_PERMISSIONS 2

class CMyApp : publid CWinApp
{
 public:
  static const TranslationPair[SECURITY_MAX_PERMISSIONS]& GetUserLevels();
 ...
};

// myapp.cpp
...
const TranslationPair[SECURITY_MAX_PERMISSIONS]& CMyApp::GetUserLevels()
{
 static const TranslationPair arUserLevels[SECURITY_MAX_PERMISSIONS] =
 {
   TranslationPair ( _T("A"), _T("A") ),
   TranslationPair ( _T("B"), _T("B") ),
 };

 return arUserLevels;
}
...



Then , wherever you need it (so wherever you formerly accessed 'arUserLevels' directly) you can access it via that static function, i.e.:

void B::func()
{
  CString s = CMyApp::GetUserLevels()[0].sKey;
}


Hope that helps,

ZOPPO



PS: The code I posted isn't tested, I just wrote it from my mind, maybe it has bugs - unfortunateley I have to leave office now, so I cannot give more help before tomorrow morning CET - sorry ...
0
 

Author Comment

by:SpringMVC
ID: 34914005
Well, thanks, I'll think a little bit more about how to "workaround" this..
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
getting a fire fox page (view page source ) in c++ 6 47
computer science syllabus 3 115
How do i run a c++ file? 15 58
keep track of class structure 1 53
Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question