pre startup initialization

N

Nolan Martin

How would I go about calling a function before the main function is called?
The function needs to be called multiple times from different locations.

I have something like this working but it is more of a hack than anything...
---FOO.cpp---
bool func() {
dostuff;
return 0;
};

---A.cpp---
bool func();
bool __dummyvar__ = func();

---B.cpp---
bool func();
bool __dummyvar__ = func();

---C.cpp---
bool func();
bool __dummyvar__ = func();

this is all done globally.
 
A

Alf P. Steinbach

* Nolan Martin:
How would I go about calling a function before the main function is called?
The function needs to be called multiple times from different locations.

I have something like this working but it is more of a hack than anything...
---FOO.cpp---
bool func() {
dostuff;
return 0;
};

---A.cpp---
bool func();
bool __dummyvar__ = func();

---B.cpp---
bool func();
bool __dummyvar__ = func();

---C.cpp---
bool func();
bool __dummyvar__ = func();

this is all done globally.

I'm sorry that I don't have a really good, simple solution.

I suspect it is because such isn't to be found anywhere because it
requires language support that isn't present in C++.

AFAIK the standard i/o streams (both C and C++) are initialized by
some mechanism not available to ordinary
non-standard-library-implementor programmers.

And note that although the order of dynamic initialization of namespace
scope objects _within_ a translation unit is well-defined (namely order
of definition), order of initialization among translation units is very
much undefined.

Also note that if func() throws it's really goodbye, so perhaps a more
"manual" scheme would be better -- more work, but safer.
 
J

JKop

Nolan Martin posted:
How would I go about calling a function before the main function is
called? The function needs to be called multiple times from different
locations.

I have something like this working but it is more of a hack than
anything... ---FOO.cpp---
bool func() {
dostuff;
return 0;
};

---A.cpp---
bool func();
bool __dummyvar__ = func();

---B.cpp---
bool func();
bool __dummyvar__ = func();

---C.cpp---
bool func();
bool __dummyvar__ = func();

this is all done globally.


That's clever! I wouldn't have thought of that, I would've
defined a global object whose contructor does stuff.

Anyway, C++ programs start at main(), there's no getting
around that, although... all global data is initialized
before main is called. Concordantly, if you want to execute
code before main(), this code must be executed as a
consequence of a global variable being initialized, no two
ways about it.

So what you've done is perfect. But... your code contains
three definitions of the same object. That's we call a
violation of the "ODR", The One Definiton Rule.

In the following code:

---FOO.cpp---
bool func()
{
//Do Stuff

return true;
}

---A.cpp---
bool func();

bool g_init1 = func();

---B.cpp---
bool func();

bool g_init2 = func();

---C.cpp---
bool func();

bool g_init3 = func();

---main.cpp---
int main()
{
;
}


When you execute this program, here's what'll happen:

func();
func();
func();
main();

g_init1, g_init2 and g_init3 will be initialized in no
particular order.

I wouldn't call what you've done a "hack", it's very simple
what going on and it works well!


-JKop
 
T

Thomas Matthews

Nolan said:
How would I go about calling a function before the main function is called?
The function needs to be called multiple times from different locations.

I have something like this working but it is more of a hack than anything...
---FOO.cpp---
bool func() {
dostuff;
return 0;
};

---A.cpp---
bool func();
bool __dummyvar__ = func();

---B.cpp---
bool func();
bool __dummyvar__ = func();

---C.cpp---
bool func();
bool __dummyvar__ = func();

this is all done globally.

Another tactic is to move your current functionality in
main() to a "secondary" function. The main() function
would call your "pre-initialize" functions then call the
secondary main function.

Just a thought, since you haven't given us any more
specifics.

In the embedded systems world, things that must be
initialized before main() are done in assembly
language.

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book
 
N

Nolan Martin

JKop said:
Nolan Martin posted:



That's clever! I wouldn't have thought of that, I would've
defined a global object whose contructor does stuff.

Anyway, C++ programs start at main(), there's no getting
around that, although... all global data is initialized
before main is called. Concordantly, if you want to execute
code before main(), this code must be executed as a
consequence of a global variable being initialized, no two
ways about it.

So what you've done is perfect. But... your code contains
three definitions of the same object. That's we call a
violation of the "ODR", The One Definiton Rule.

In the following code:

---FOO.cpp---
bool func()
{
//Do Stuff

return true;
}

---A.cpp---
bool func();

bool g_init1 = func();

---B.cpp---
bool func();

bool g_init2 = func();

---C.cpp---
bool func();

bool g_init3 = func();

---main.cpp---
int main()
{
;
}


When you execute this program, here's what'll happen:

func();
func();
func();
main();

g_init1, g_init2 and g_init3 will be initialized in no
particular order.

I wouldn't call what you've done a "hack", it's very simple
what going on and it works well!


-JKop

Oops, meant for __dummypointer__ to be declared static so that is has strict
internal linkage, then it wont be multipli defined. Its more efficient that
way.
 
N

Nolan Martin

Nolan Martin said:
Oops, meant for __dummypointer__ to be declared static so that is has strict
internal linkage, then it wont be multipli defined. Its more efficient that
way.

And it also allows you to use this technique in macros.
 
T

tom_usenet

How would I go about calling a function before the main function is called?
The function needs to be called multiple times from different locations.

I have something like this working but it is more of a hack than anything...
---FOO.cpp---
bool func() {
dostuff;
return 0;
};

You don't need it to return bool, void is fine.
---A.cpp---
bool func();
bool __dummyvar__ = func();

That name is illegal because of the underscores - user code shouldn't
use double underscores at all, to avoid clashing with library and
compiler stuff and with the name mangling algorithm.

namespace
{
bool dummy = (func(), true); //use of comma operator
}
---B.cpp---
bool func();
bool __dummyvar__ = func();

---C.cpp---
bool func();
bool __dummyvar__ = func();

this is all done globally.

Do you call the same function 3 times for a good reason? Why not just
call it once?

The final point to notice is that global variables are not necessarily
initialized before main is entered, but only before the first function
defined in the same translation unit as the global is called. In
practice this is only really a problem for static libraries (which
strip out unreferenced global variables if you're not careful) and
with DLLs where initialization will be deferred until the DLL is
loaded (and Dllmain is called on Windows).

Tom
 
N

Nolan Martin

tom_usenet said:
You don't need it to return bool, void is fine.


That name is illegal because of the underscores - user code shouldn't
use double underscores at all, to avoid clashing with library and
compiler stuff and with the name mangling algorithm.

namespace
{
bool dummy = (func(), true); //use of comma operator
}


Do you call the same function 3 times for a good reason? Why not just
call it once?

The final point to notice is that global variables are not necessarily
initialized before main is entered, but only before the first function
defined in the same translation unit as the global is called. In
practice this is only really a problem for static libraries (which
strip out unreferenced global variables if you're not careful) and
with DLLs where initialization will be deferred until the DLL is
loaded (and Dllmain is called on Windows).

Tom

you have all valid points. but that is not my application.

I am writing a portable serialization library, you can see it below. I
havent implemented the ability to serialize pointers yet thats what the
TypeMap is for. It is initialised when the program starts and is filled with
the names and helper constructors of all the declared classes. The name of
the class is then written to a file preceding the classes data being
serialized so that when deserializing it can lookup the proper constructor
for the class.
I will post the complete code when i can get past this damn error that the
std::map causes when using it with the SDL multithreading librarys.

the library is used like this:
---foo.h--------

class foo
{
int var1, var2, var3, var4;
DECLARE_CLASS(foo)
void Serialize(FILE* file);
};

---foo.cpp----
#include "Serialize.h"
#include "foo.h"

IMPLEMENT_CLASS(foo)

void foo::Serialize(FILE* file)
{
file, var1, var2, var3, var4;
}

--------------Serialize.h---------------
#pragma once

#include <stdio.h>

#include <map>

#include <string>

//Global members
****************************************************************************
******

extern bool IsLoading;

extern map<string, void*> TypeMap;

bool __addclass(const char* name, void* ptr);

#define DECLARE_CLASS(class_name) \
static void* CreateInstance(void); \
friend FILE& operator,(FILE& file, class_name& Ob); \
friend FILE& operator,(FILE& file, class_name*& Ob);



#define IMPLEMENT_CLASS(class_name) \
static bool __dummyvar__ = __addclass(#class_name,
class_name::CreateInstance); \
void* class_name::CreateInstance(void) { return new class_name; } \
FILE& operator,(FILE& file, class_name& Ob) { Ob.Serialize(file); return
file; }; \
FILE& operator,(FILE& file, class_name*& Ob) { if (IsLoading) Ob = new
class_name; Ob->Serialize(file); return file; };

FILE& operator,(FILE& file, char var);

FILE& operator,(FILE& file, bool var);

FILE& operator,(FILE& file, short var);

FILE& operator,(FILE& file, int var);

FILE& operator,(FILE& file, long var);

FILE& operator,(FILE& file, float var);

FILE& operator,(FILE& file, double var);

FILE& operator,(FILE& file, long double var);

FILE& operator,(FILE& file, unsigned long var);

FILE& operator,(FILE& file, char*& var);

FILE& operator,(FILE& file, bool*& var);

FILE& operator,(FILE& file, short*& var);

FILE& operator,(FILE& file, int*& var);

FILE& operator,(FILE& file, long*& var);

FILE& operator,(FILE& file, float*& var);

FILE& operator,(FILE& file, double*& var);

FILE& operator,(FILE& file, long double*& var);

FILE& operator,(FILE& file, unsigned long*& var);

void SerializeCharArray(FILE& file, char* array, unsigned long length);

char* DeSerializeCharArray(FILE& file, unsigned long& length);



--------------Serialize.cpp---------------

#include "stdafx.h"

//Global members
****************************************************************************
******

bool IsLoading = NULL;

map<string, void*> TypeMap;

bool __addclass(const char* name, void* ptr) {

TypeMap.insert(make_pair(name, ptr)); //the error occurs here if anyone
knows how to resolve it

return 0;

};

FILE& operator,(FILE& file, char var) { if (IsLoading) fread(&var,
sizeof(char), 1, &file);

else fwrite(&var, sizeof(char), 1, &file);

return file; };

FILE& operator,(FILE& file, bool var) { if (IsLoading) fread(&var,
sizeof(bool), 1, &file);

else fwrite(&var, sizeof(bool), 1, &file);

return file; };

FILE& operator,(FILE& file, short var) { if (IsLoading) fread(&var,
sizeof(short), 1, &file);

else fwrite(&var, sizeof(short), 1, &file);

return file; };

FILE& operator,(FILE& file, int var) { if (IsLoading) fread(&var,
sizeof(int), 1, &file);

else fwrite(&var, sizeof(int), 1, &file);

return file; };

FILE& operator,(FILE& file, long var) { if (IsLoading) fread(&var,
sizeof(long), 1, &file);

else fwrite(&var, sizeof(long), 1, &file);

return file; };

FILE& operator,(FILE& file, float var) { if (IsLoading) fread(&var,
sizeof(float), 1, &file);

else fwrite(&var, sizeof(float), 1, &file);

return file; };

FILE& operator,(FILE& file, double var) { if (IsLoading) fread(&var,
sizeof(double), 1, &file);

else fwrite(&var, sizeof(double), 1, &file);

return file; };

FILE& operator,(FILE& file, long double var) { if (IsLoading) fwrite(&var,
sizeof(long double), 1, &file);

else fwrite(&var, sizeof(long double), 1, &file);

return file; };

FILE& operator,(FILE& file, unsigned long var) { if (IsLoading) fread(&var,
sizeof(unsigned long), 1, &file);

else fwrite(&var, sizeof(unsigned long), 1, &file);

return file; };

FILE& operator,(FILE& file, char*& var) { if (IsLoading) {var = new char;
fread(var, sizeof(char), 1, &file); }

else fwrite(var, sizeof(char), 1, &file);

return file; };

FILE& operator,(FILE& file, bool*& var) { if (IsLoading) {var = new bool;
fread(var, sizeof(bool), 1, &file); }

else fwrite(var, sizeof(bool), 1, &file);

return file; };

FILE& operator,(FILE& file, short*& var) { if (IsLoading) {var = new short;
fread(var, sizeof(short), 1, &file); }

else fwrite(var, sizeof(short), 1, &file);

return file; };

FILE& operator,(FILE& file, int*& var) { if (IsLoading) {var = new int;
fread(var, sizeof(int), 1, &file); }

else fwrite(var, sizeof(int), 1, &file);

return file; };

FILE& operator,(FILE& file, long*& var) { if (IsLoading) {var = new long;
fread(var, sizeof(long), 1, &file); }

else fwrite(var, sizeof(long), 1, &file);

return file; };

FILE& operator,(FILE& file, float*& var) { if (IsLoading) {var = new float;
fread(var, sizeof(float), 1, &file); }

else fwrite(var, sizeof(float), 1, &file);

return file; };

FILE& operator,(FILE& file, double*& var) { if (IsLoading) {var = new
double; fread(var, sizeof(double), 1, &file); }

else fwrite(var, sizeof(double), 1, &file);

return file; };

FILE& operator,(FILE& file, long double*& var) { if (IsLoading) {var = new
long double; fwrite(var, sizeof(long double), 1, &file); }

else fwrite(var, sizeof(long double), 1, &file);

return file; };

FILE& operator,(FILE& file, unsigned long*& var) { if (IsLoading) {var = new
unsigned long; fread(var, sizeof(unsigned long), 1, &file); }

else fwrite(var, sizeof(unsigned long), 1, &file);

return file; };

void SerializeCharArray(FILE& file, char* array, unsigned long length)

{

fwrite(&length, sizeof(unsigned long), 1, &file);

fwrite(array, sizeof(char), length+1, &file);

};

char* DeSerializeCharArray(FILE& file, unsigned long& length)

{

fread(&length, sizeof(unsigned long), 1, &file);

char* array = new char[length+1];

fread(array, sizeof(char), length+1, &file);

return array;

};
 
J

Jeff Flinn

Nolan Martin said:
you have all valid points. but that is not my application.

I am writing a portable serialization library, you can see it below. I
havent implemented the ability to serialize pointers yet thats what the

Have you seen the serialization library which is soon to be part of
www.boost.org? You can get the latest per-relase version at www.rrsd.com.

Jeff F
 
B

Bob Hairgrove

How would I go about calling a function before the main function is called?
The function needs to be called multiple times from different locations.

I have something like this working but it is more of a hack than anything...
---FOO.cpp---
bool func() {
dostuff;
return 0;
};

---A.cpp---
bool func();
bool __dummyvar__ = func();

---B.cpp---
bool func();
bool __dummyvar__ = func();

---C.cpp---
bool func();
bool __dummyvar__ = func();

this is all done globally.

There is nothing in standard C++ you can use except for the fact that
static objects at global scope are constructed prior to calling
main(). You could initialize some such object in each cpp file whose
constructor did the necessary work (i.e. calls your func()). Note that
the order in which the static objects are created would correspond to
the order in which the object files are linked.

Additionally, there are non-standard #pragmas which some compilers
offer if you need more low-level control, e.g. there is #pragma
startup for Borland's C++ compiler, and #pragma init_seg for MSVC++.

PS - don't use leading underscores in any identifiers; these are
reserved for the compiler and/or STL.
 
B

Bob Hairgrove

Oops, I made a somewhat misleading statement: it is
implementation-defined whether static objects at global scope are
initialized before main() is entered. Please refer to the C++
standard, section 3.6.2 for details.

Note that the CRT will usually execute its own initialization code
before any other user code is executed.
 

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

Forum statistics

Threads
474,174
Messages
2,570,940
Members
47,485
Latest member
Andrewayne909

Latest Threads

Top