Thanks in advance for any help / insight on this matter.
1) This piece of code (inside the class ReassignCaseRequestHandler :
public CaseRequestHandler implementation file) calls a const static
data member (CaseRequestHandler::PARAM_CALLING_TRANSACTION) (see code
below). The problem I am having is that this static data member (first
param to MessageParameter) is uninitialized (bss section).
Platform: CentOS 5
gcc: version 4.1.2 20080704 (Red Hat 4.1.2-48)
const MessageParameter*
ReassignCaseRequestHandler::requestParameters1[] =
{
new
MessageParameter( CaseRequestHandler::PARAM_CALLING_TRANSACTION, true,
1, 20, MessageParameter::ALPHA_NUMERIC ),
......
};
ReassignCaseRequestHandler::ReassignCaseRequestHandler()
{
addRequestVersion( 1, requestParameters1 );
}
2) Here's how the CaseRequestHandler::PARAM_CALLING_TRANSACTION is
initialized in the base class:
In the header file:
class CaseRequestHandler
{
public:
static const string PARAM_CALLING_TRANSACTION;
.......
};
In the .cpp file:
using namespace std;
#include <string>
#include "CaseRequestHandler.h"
const string CaseRequestHandler::PARAM_CALLING_TRANSACTION =
"CALLING_TRANSACTION";
........
3) This is how the data appears inside the debugger (gdb). NOTE: on
frame #1, paramName is null.
Program terminated with signal 11, Segmentation fault.
#0 0x0000003479a9c8c8 in std::basic_string<char,
std::char_traits<char>, std::allocator<char>
>::basic_string(std::basic_string<char, std::char_traits<char>,
std::allocator<char> > const&) () from /usr/lib64/libstdc++.so.6
(gdb) where
#0 0x0000003479a9c8c8 in std::basic_string<char,
std::char_traits<char>, std::allocator<char>
>::basic_string(std::basic_string<char, std::char_traits<char>,
std::allocator<char> > const&) () from /usr/lib64/libstdc++.so.6
#1 0x00002ae91cf7f5bb in MessageParameter::MessageParameter
(this=0xa84380, paramName=..., paramRequired=true,
paramMinLength=1, paramMaxLength=20, paramType=ALPHA_NUMERIC) at
MessageParameter.c:15
#2 0x00002ae91cf6b2ba in __static_initialization_and_destruction_0
(__initialize_p=1, __priority=65535)
at uidbcasereassign.cpp:214
#3 0x00002ae91cf6b511 in global constructors keyed to
_ZN26ReassignCaseRequestHandler17PARAM_NEW_USER_IDE() ()
at uidbcasereassign.cpp:709
#4 0x00002ae91cfe5536 in __do_global_ctors_aux () from /home/
euci216/2.36.1.3.L/lib/libuidb15_b.so.0
#5 0x00002ae91cf254a3 in _init () from /home/euci216/2.36.1.3.L/lib/
libuidb15_b.so.0
#6 0x00002ae91ef4f990 in ?? ()
#7 0x0000003472e0d24b in call_init () from /lib64/ld-linux-x86-64.so.
2
#8 0x0000003472e0d355 in _dl_init_internal () from /lib64/ld-linux-
x86-64.so.2
#9 0x0000003472e00aaa in _dl_start_user () from /lib64/ld-linux-
x86-64.so.2
#10 0x0000000000000001 in ?? ()
#11 0x00007fff409c0789 in ?? ()
#12 0x0000000000000000 in ?? ()
(gdb) frame 1
#1 0x00002ae91cf7f5bb in MessageParameter::MessageParameter
(this=0xa84380, paramName=..., paramRequired=true,
paramMinLength=1, paramMaxLength=20, paramType=ALPHA_NUMERIC) at
MessageParameter.c:15
15 type( paramType )
(gdb) print paramName
$1 = (const MessageParameter::string &) @0x2ae91d21e218: {static npos
= 18446744073709551615,
_M_dataplus = {<std::allocator<char>> =
{<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data
fields>},
_M_p = 0x0}}
Cheers,
Nick R.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
[..]
> const MessageParameter*
> ReassignCaseRequestHandler::requestParameters1[] =
> {
> new
> MessageParameter( CaseRequestHandler::PARAM_CALLING_TRANSACTION, true,
> 1, 20, MessageParameter::ALPHA_NUMERIC ),
> ......
> };
>
> ReassignCaseRequestHandler::ReassignCaseRequestHandler()
> {
> addRequestVersion( 1, requestParameters1 );
> }
>
> 2) Here's how the CaseRequestHandler::PARAM_CALLING_TRANSACTION is
> initialized in the base class:
>
> In the header file:
> class CaseRequestHandler
> {
> public:
> static const string PARAM_CALLING_TRANSACTION;
> .......
> };
>
> In the .cpp file:
> using namespace std;
>
> #include <string>
> #include "CaseRequestHandler.h"
>
> const string CaseRequestHandler::PARAM_CALLING_TRANSACTION =
> "CALLING_TRANSACTION";
> ........
Without looking into the details it looks to me as if
you are attempting to access a global variable defined
in translation unit (TU) A within TU B where the variable
has not yet been initialized. Note that the initialization
order among variables in different TUs is unspecified. In
fact, the situation is even worse in the sense that the
initialization of such variables is unsequenced.
To fix your problem, you could use a function with
a local static variable, e.g.
// Header:
class CaseRequestHandler
{
public:
static const string& param_calling_transaction();
.......
};
// Cpp:
const string& CaseRequestHandler::param_calling_transaction()
{
static const string result("CALLING_TRANSACTION");
return result;
}
Local static variables are initialized when the code flow
reaches them the first time and succeeds.
HTH & Greetings from Bremen,
Daniel Krügler
On 27 aug, 05:06, sil <schit...@gmail.com> wrote:
> Hi All,
> ...
Aren't you initializing one static variable
(ReassignCaseRequestHandler::requestParameters1) with another
(CaseRequestHandler::PARAM_CALLING_TRANSACTION)? You don't have any
control on the order of how static variables are initialized. I
haven't taken a detailed look in the debugger output, but my guess is
CaseRequestHandler::PARAM_CALLING_TRANSACTION isn't initialized yet at
the point where you're trying to initialize
ReassignCaseRequestHandler::requestParameters1.
When it comes to static/global initialization order you can save
yourself a lot of trouble by sticking to POD.
static const char[] CaseRequestHandler::PARAM_CALLING_TRANSACTION =
"CALLING_TRANSACTION";
Will give you no initialization problems because it is pure data and
the only cost is extra conversions to std::string if you use it a
lot.
P.S. Please please please do NOT make the appallingly common mistake
of writing:
static const char* CaseRequestHandler::PARAM_CALLING_TRANSACTION =
"CALLING_TRANSACTION";
P.P.S. If you really want a string then consider using a const
std::string* pointer and get method that does lazy construction (but
beware threading problems)
Except for the static variable name being all caps with underscores
(this style should be reserved for macro names), and the fact that
your pointer is not const, I don't understand why you find this
appalling.
Of course, I would do it like this...
static char const * const CaseRequestHandler::ParamCallingTransaction
= "CALLING_TRANSACTION";
This construct has the possible (not guaranteed) added benefit of
allowing the compiler to fold constant strings and use the same
pointer for strings with the same value. The compiler can't use the
same address for different char arrays that contain the same string
since they are different objects. Not a likely benefit in this case,
but the concept still applies. This string constant is also guaranteed
to be valid before any dynamic construction of objects at namespace
scope, so there is no "static initialization order fiasco" to contend
with.
So what's wrong with this?
Tony
Because
a) The pointer isn't const when clearly it is intended to be.
b) You gratuitously wastes a pointer's worth of storage
c) It's potentially slower depending on your processor
You apparently didn't read the part you snipped from my reply...
Copy from prior post:
Of course, I would do it like this...
static char const * const
CaseRequestHandler::ParamCallingTransaction
> b) You gratuitously wastes a pointer's worth of storage
Premature optimization. (Are you kidding?)
> c) It's potentially slower depending on your processor
Premature optimization. Benchmark please?
The other part you snipped pointed out a potential storage benefit...
Copy from prior post:
This construct has the possible (not guaranteed) added benefit of
allowing the compiler to fold constant strings and use the same
pointer for strings with the same value. The compiler can't use the
same address for different char arrays that contain the same string
since they are different objects. Not a likely benefit in this case,
but the concept still applies.
Tony
and I forgot
d) You can't compute the string length at compile time using sizeof
> > b) You gratuitously wastes a pointer's worth of storage
>
> Premature optimization. (Are you kidding?)
A premature *habitual* optimization has no measurable incremental
programmer time cost, thus is worth training when not prohibited by
applicable coding standards.
> The other part you snipped pointed out a potential storage benefit...
>
> Copy from prior post:
> This construct has the possible (not guaranteed) added benefit of
> allowing the compiler to fold constant strings and use the same
> pointer for strings with the same value. The compiler can't use the
> same address for different char arrays that contain the same string
> since they are different objects. Not a likely benefit in this case,
> but the concept still applies.
#define INTERESTING_STRING "Interesting string"
works even better for this purpose.