Currently, I've created a simple error handling system to check whether a pointer is valid by checking for nullptr like so:
inline void ErrReport(const char8* fileOfError, int32 lineNumberOfError, const Blz::string c_errMessage)
{
ErrorContext::LogContext();
LOG(" ERROR: %s\n", c_errMessage.c_str());
LOG(" In %s: %i\n\n", fileOfError, lineNumberOfError);
exit(0);
}
#if(_DEBUG)
#define ERRASSERT(test, msg) do {if (!(test)) Blz::Err::ErrReport(__FILE__, __LINE__, msg);} while (0)
#endif
I can then call ERRASSERT in my code like so:
unsgined char* imageData = LoadImage("PathToImage");
ERRASSERT(imageData, "Image did not load properly");
Right now, in order to do something similar with non-pointer objects I have a Check() function to see if an object has been initialized or not:
template<typename T> inline bool Check(boost::outcome::expected<T>& obj)
{
if (obj)
return true;
else
return false;
}
With this code, if I understand how to use outcome::expected correctly, I would then just call the above function within my ERRASSERT and everything should work similiarly
boost::outcome::expected<ObjectType> obj = functionReturnsObj();
ERRASSERT(Check(obj), "Object not initialized!);
My question:
Is there a better way to check if an object is initialized without having to wrap everything in boost::outcome::expected? Are there even many scenarios where an object wouldn't be initialized given C++ automatically initializes objects upon creation? Should I even be worried about this?
Is there a better way to check if an object is initialized
Don't.
Are there even many scenarios where an object wouldn't be initialized given C++ automatically initializes objects upon creation?
Yes, and it doesn't (always).
But that's the programmer's responsibility (and you can usually rely on compiler warnings to catch silly mistakes).
Should I even be worried about this?
No.
I just want to elaborate a bit on Should I even be worried about this? in addition to #BoundaryImposition's answer.
An uninitialized C++ object may cause you issues in certain cases. If you have Foo and create an instance f as below, then f.a and f.b are not initialized and you should not assume they are 0.
struct Foo { int a; int b; };
Foo f;
Related
I have a class which is loaded from an external file, so ideally I would want its constructor to load from a given path if the load fails, I will want to throw an error if the file is not found/not readable (Throwing errors from constructors is not a horrible idea, see ISO's FAQ).
There is a problem with this though, I want to handle errors myself in some controlled manner, and I want to do that immediately, so I need to put a try-catch statement around the constructor for this object ... and if I do that, the object is not declared outside the try statement, i.e.:
//in my_class.hpp
class my_class
{
...
public:
my_class(string path);//Throws file not found, or other error error
...
};
//anywhere my_class is needed
try
{
my_class my_object(string);
}
catch(/*Whatever error I am interesetd in*/)
{
//error handling
}
//Problem... now my_object doesn't exist anymore
I have tried a number of ways of getting around it, but I don't really like any of them:
Firstly, I could use a pointer to my_class instead of the class itself:
my_class* my_pointer;
try
{
my_class my_pointer = new my_class(string);
}
catch(/*Whatever error I am interesetd in*/)
{
//error handling
}
The problem is that the instance of this object doesn't always end up in the same object which created it, so deleting all pointers correctly would be easy to do wrong, and besides, I personally think it is ugly to have some objects be pointers to objects, and have most others be "regular objects".
Secondly, I could use a vector with only one element in much the same way:
std::vector<my_class> single_vector;
try
{
single_vector.push_back(my_class(string));
single_vector.shrink_to_fit();
}
catch(/*Whatever error I am interesetd in*/)
{
//error handling
}
I don't like the idea of having a lot of single-element vectors though.
Thirdly, I can create an empty faux constructor and use another loading function, i.e.
//in my_class.hpp
class my_class
{
...
public:
my_class() {}// Faux constructor which does nothing
void load(string path);//All the code in the constructor has been moved here
...
};
//anywhere my_class is needed
my_class my_object
try
{
my_object.load(path);
}
catch(/*Whatever error I am interesetd in*/)
{
//error handling
}
This works, but largely defeats the purpose of having a constructor, so I don't really like this either.
So my question is, which of these methods for constructing an object, which may throw errors in the constructor, is the best (or least bad)? and are there better ways of doing this?
Edit: Why don't you just use the object within the try-statement
Because the object may need to be created as the program is first started, and stopped much later. In the most extreme case (which I do actually need in this case also) that would essentially be:
int main()
{
try
{
//... things which might fail
//A few hundred lines of code
}
catch(/*whaveter*/)
{
}
}
I think this makes my code hard to read since the catch statement will be very far from where things actually went wrong.
One possibility is to wrap the construction and error handling in a function, returning the constructed object. Example :
#include <string>
class my_class {
public:
my_class(std::string path);
};
my_class make_my_object(std::string path)
{
try {
return {std::move(path)};
}
catch(...) {
// Handle however you want
}
}
int main()
{
auto my_object = make_my_object("this path doesn't exist");
}
But beware that the example is incomplete because it isn't clear what you intend to do when construction fails. The catch block has to either return something, throw or terminate.
If you could return a different instance, one with a "bad" or "default" state, you could have just initialized your instance to that state in my_class(std::string path) when it was determined the path is invalid. So in that case, the try/catch block is not needed.
If you rethrow the exception, then there is no point in catching it in the first place. In that case, the try/catch block is also not needed, unless you want to do a bit of extra work, like logging.
If you want to terminate, you can just let the exception go uncaught. Again, in that case, the try/catch block is not needed.
The real solution here is probably to not use a try/catch block at all, unless there is actually error handling you can do that shouldn't be implemented as part of my_class which isn't made apparent in the question (maybe a fallback path?).
and if I do that, the object is not declared outside the try statement
I have tried a number of ways of getting around it
That doesn't need to be a problem. There's not necessarily need to get around it. Simply use the object within the try statement.
If you really cannot have the try block around the entire lifetime, then this is a use case for std::optional:
std::optional<my_class> maybe_my_object;
try {
maybe_my_object.emplace(string);
} catch(...) {}
The problem is that the instance of this object doesn't always end up in the same object which created it, so deleting all pointers correctly would be easy to do wrong,
A pointer returned by new is correct to delete. In the error case, simply set the pointer to null and there would be no problem. That said, use a smart pointer instead for dynamic allocation, if you were to use this approach.
single_vector.push_back(my_class(string));
single_vector.shrink_to_fit();
Don't push and shrink when you know the number of objects that are going to be in the vector. Use reserve instead if you were to use this approach.
The object creation can fail because a resource is unavailable. It's not the creation which fails; it is a prerequisite which is not fulfilled.
Consequently, separate these two concerns: First obtain all resources and then, if that succeeded, create the object with these resources and use it. The object creation as such in this design cannot fail, the constructor is nothrow; it is trivial boilerplate code (copy data etc.). If, on the other hand, resource acquisition failed, object creation and object use are both skipped: Your problem with existing but unusable objects is gone.
Responding to your edit about try/catch comprising the entire program: Exceptions as error indicators are better suited for things which are done in many places at various times in a program because they guarantee error handling (by default through an abort) while separating it from the normal control flow. This is impossible to do with classic return value examination, which leaves us with a choice between unreadable or unreliable programs.
But if you have long-lived objects which are created only rarely (in your example: only at startup) you don't need exceptions. As you said, constructor exceptions guarantee that only properly initialized objects can be used. But if such an object is only created at startup this danger is low. You check for success one way or another and exit the program which cannot perform its purpose if the initial resource acquisition failed. This way the error is handled where it occurred. Even in less extreme cases (e.g. when an object is created at the beginning of a large function other than main) this may be the simpler solution.
In code, my suggestion looks like this:
struct T2;
struct myEx { myEx(const char *); };
void exit(int);
T1 *acquireResource1(); // e.g. read file
T2 *acquireResource2(); // e.g. connect to db
void log(const char *what);
class ObjT
{
public:
struct RsrcT
{
T1 *mT1;
T2 *mT2;
operator bool() { return mT1 && mT2; }
};
ObjT(const RsrcT& res) noexcept
{
// initialize from file data etc.
}
// more member functions using data from file and db
};
int main()
{
ObjT::RsrcT rsrc = { acquireResource1(), acquireResource2() };
if(!rsrc)
{
log("bummer");
exit(1);
}
///////////////////////////////////////////////////
// all resources are available. "Real" code starts here.
///////////////////////////////////////////////////
ObjT obj(rsrc);
// 1000 lines of code using obj
}
I have this method:
bool CDemoPickerDlg::IsStudentTalk(CString strAssignment)
{
bool bStudentTalk = false;
CString strTalkMain, strTalkClass;
if (theApp.UseTranslationINI())
{
strTalkMain = theApp.GetSMMethod(_T("IDS_STR_HISTORY_TALK_MAIN"));
strTalkClass = theApp.GetSMMethod(_T("IDS_STR_HISTORY_TALK_AUX"));
}
else
{
strTalkMain.LoadString(IDS_STR_HISTORY_TALK_MAIN);
strTalkClass.LoadString(IDS_STR_HISTORY_TALK_AUX);
}
int iTalkMainLen = strTalkMain.GetLength();
int iTalkClassLen = strTalkClass.GetLength();
if (strAssignment.Left(iTalkMainLen) == strTalkMain ||
strAssignment.Left(iTalkClassLen) == strTalkClass)
{
bStudentTalk = true;
}
return bStudentTalk;
}
It is called multiple times. Without added "member variables" to the class to cache values is there any other way to create the values for the two CString and int values just the once? As they will not change for the duration of the program.
The method above is static. I know about assigning a value to a static variable but I understand that can only be done once at the time of declaration. Have I miss-understood that?
You can use a static constant (or variable, but why make it variable if it isn't supposed to be changed?) at function scope:
static CString const someImmutableText = <some initializer>;
The placeholder <some initializer> above can be a literal, a function call or any other expression that you can initialize a CString from. The static makes sure the object is only created once and subsequently only initialized once, too.
#Ulrich's answer will of course work fine, but if <some initializer> is non-trivial there is a hidden downside - as of C++11, the compiler is required to generate a threadsafe initialiser.
This has minimal runtime overhead but it does generate quite a lot of code, see at Godbolt, and if you have a lot of these then this can add up.
If there are no multi-threading issues (which generally there aren't, especially in initialisation code), then there is a simple alternative which will eliminate this code. In fact, it's so simple that it's barely worth posting at all, but I'll do it here anyway for completeness. It's just this; please excuse the anglicisms:
static bool initialised;
static Foo *initialise_me;
static Bar *initialise_me_too;
...
if (!initialised)
{
initialise_me = new Foo (...);
initialise_me_too = new Bar (...);
...
initialised = true;
}
...
Note that the variables to be initialised are declared as raw pointers here and allocated with new. This is done for a reason - the one thing you most definitely don't want is to call constructors at the point where you declare these variables, else you'll be right back where you started. There are no object lifetime issues because the variables remain in existence for the entire duration of the program, so it's all good.
And, in fact, you don't actually need that bool at all - just test (say) initialise_me against nullptr.
Context: I'm trying to memoize an object of a template class. Right now, the class is a deeply nested data structure full of unique pointers, and so doesn't have a copy constructor (and so would be impossible to cache, as far as I know). However, in the future, I would like to allow memoization if a copy constructor is available. I tried the following code:
// some function here... {
static std::unordered_map<State, Result> cache;
return [c, ToValue](State state) {
if (cache.find(state) != cache.end()) {
std::cout << "retrieving Literal from cache\n";
if (std::is_copy_constructible<Result>::value) {
return cache[state];
}
}
// calculate and return a Result
This code doesn't compile because Result doesn't have a copy constructor. Is there any way to get around this? Google is being quite unhelpful.
I'm presuming the error you are getting is that return cache[state]; cannot be compiled when the object is not copy-constructible. To fix that you can write:
if constexpr (std::is_copy_constructible<Result>::value) {
return cache[state];
}
If you are still having trouble then post a MCVE that has the error.
As others have commented, the question is rather ill-defined and a bit confused, but do you need to actually copy an object in order to cache it?
Actually, no. You can use std::shared_ptr to share ownership of the object between the creator, any consumers, and the cache. If nothing else, this is much more efficient if your object is a complex one. It will also work for any type of object, copyable or not.
Example (I'm going to use the word Key rather than State, for what I hope are obvious reasons).
Given these declarations:
class MyKey
{
// ....
};
class MyCacheableObject
{
// Constructor
MyCacheableObject (int a, int b, int c) { ... }
// ...
};
static std::unordered_map<MyKey, std::shared_ptr<MyCacheableObject>> cache; // or std::map
You can do this (please note that there are other ways to make a std::shared_ptr, see here):
std::shared_ptr<MyCacheableObject> CreateCacheableObject (int a, int b, int c)
{
return std::make_shared<MyCacheableObject> (MyCacheableObject (a, b, c));
}
And then, assuming you have a key you plan to use to retrieve the object from the cache later on, you can do:
MyKey someKey = ...;
std::shared_ptr<MyCacheableObject> newObject = CreateCacheableObject (1, 2, 3);
// ... setup / use `newObject` in whatever way is appropriate to your use-case
cache [someKey] = newObject;
And you can of course retrieve the object from the cache (if it's in there) via:
auto retrievedObject = cache.find (someKey)
if (retrievedObject != cache.end())
...
So this question is not about whether an object is copyable at all. It's about (shared) ownership and std::shared_ptr takes care of all that for you, you don't really have to think about it. Oy vay.
There's a live demo, to show that this all compiles, here.
I have a C (nested) structure that I would like to automagically initialize and destroy in my code.
I am compiling with GCC (4.4.3) on Linux. I am vaguely aware of GCC function attributes constructor and destructor, but the construction/destruction they provide seem to relate to the entire program (i.e. before main() is called etc).
I want to be able to have different init/cleanup funcs for different data types - is this C++ like behaviour something that I can emulate using POC?
I have included the C++ tag because this is really C++ behaviour I am trying to emulate in C.
There's no way to do this automatically, at least not in any portable manner. In C you'd typically have functions that work somewhat like constructors and destructors — they (de)allocate memory and (de)initialize fields —, except they have to be called explicitly:
typedef struct{} MyStruct;
MyStruct *MyStruct_New(void);
void MyStruct_Free(MyStruct *obj);
The language was simply not designed for this and you shouldn't try to force it, imo. If you want to have automatic destruction, you shouldn't be using C.
#define your way through the problem...
As pointed out by previous authors there is no automatic way of doing what you are asking, which sadly is kind of obvious since C doesn't have any way of doing true OOP.
But a programmer can always hack him or herself through any kind of obstacle.. At the end of this post I wrote you a sample hack to circumvent the problem.
There are methods of cleaning up the macro provided, though it won't be as portable.
C99 implementation: http://ideone.com/9XcCt
C89 implementation: http://ideone.com/WYrjU
- C99 implementation
#include <stdio.h>
#include <stdlib.h>
...
#define SCOPIFY(TYPE,NAME, ...) { \
ctor_ ## TYPE(& NAME); \
__VA_ARGS__ \
dtor_ ## TYPE(& NAME); \
} (void)0
...
typedef struct {
int * p;
} Obj;
void
ctor_Obj (Obj* this) {
this->p = malloc (sizeof (int));
*this->p = 123;
fprintf (stderr, "Obj::ctor, (this -> %p)\n", (void*)this);
}
void
dtor_Obj (Obj* this) {
free (this->p);
fprintf (stderr, "Obj::dtor, (this -> %p)\n", (void*)this);
}
...
int
main (int argc, char *argv[])
{
Obj o1, o2;
SCOPIFY (Obj, o1,
fprintf (stderr, " o1.p -> %d\n", *o1.p);
SCOPIFY (Obj, o2,
int a, b;
fprintf (stderr, " o2.p -> %d\n", *o2.p);
(*o1.p) += (*o2.p);
);
fprintf (stderr, " o1.p -> %d\n", *o1.p);
);
return 0;
}
output (http://ideone.com/WYrjU)
Obj::ctor, (this -> 0xbf8f05ac)
o1.p -> 123
Obj::ctor, (this -> 0xbf8f05a8)
o2.p -> 123
Obj::dtor, (this -> 0xbf8f05a8)
o1.p -> 246
Obj::dtor, (this -> 0xbf8f05ac)
From what you write, I figure that you know already how to write init and destroy functions that eventually use their counterparts for individual parts recursively.
Yes, there is no standard mechanism in C that would allow for something like automatic construction or destruction.
Construction can be somewhat replace by writing an initializer macro. Designated initializers come handy for that
#define TOTO_INITIALIZER(TUTU_PARAM, TATA_PARAM) \
{ \
.tata_member = TATA_INITIALIZER(TATA_PARAM), \
.tutu_member = TUTU_INITIALIZER(TUTU_PARAM), \
}
since they make that such code robust against reordering of members.
For destructors there is nothing that can be coupled to a variable or data type. The only thing I know of what is possible is scope based resource management that in C you can implement through hidden for-scope local variables.
There's no default way to have a function automatically called when you create a struct. Here's an example of a creation and initialisation function set for a certain type of struct:
// Simple struct that holds an ID number and a file pointer.
typedef struct
{
int id;
FILE *data;
} Datum;
// Function to create a Datum from a given file.
Datum *create_datum(const char *fname)
{
// Create Datum object.
Datum *d = (Datum*)malloc(sizeof(Datum));
// malloc may return NULL if we're out of memory.
if(d)
{
// Initialise ID to something.
d->id = 0;
// Open filename passed.
d->data = fopen(fname, "r");
}
return d;
}
// Function to safely destroy a Datum. This function takes a pointer-pointer so
// that it can set the pointer to NULL after deleting the object. Saves you
// from dangling pointers.
void destroy_datum(Datum **dp)
{
if(!dp)
return;
// Get a plain pointer for convenience
Datum *d = *dp;
if(d)
{
// Close the file.
fclose(d->data);
// Delete the object.
free(d);
// Set the pointer to NULL.
*dp = NULL;
}
}
// Now use these functions:
int main(void)
{
Datum *datum = create_datum("test.txt");
if(datum)
{
// Do some things!
}
destroy_datum(&datum);
// datum is now equal to NULL.
}
Hope that helps! Like Homunculus has said, C isn't a great language if you need to do a lot of this sort of stuff - but sometimes you just want to abstract away the process of creating a struct, as well as cleaning it up. This is especially helpful in modular design, where a module can provide the create_ and destroy_ interface functions, and hide the actual implementation of those.
I did not see the gcc tag, but since the original poster mention explicit use of GCC constructor/destructor attributes:
https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html#index-g_t_0040code_007bconstructor_007d-function-attribute-2500
I'd like to point out that there is also the cleanup attribute:
https://gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/Common-Variable-Attributes.html#index-g_t_0040code_007bcleanup_007d-variable-attribute-3486
cleanup (cleanup_function)
The cleanup attribute runs a function when
the variable goes out of scope. This attribute can only be applied to
auto function scope variables; it may not be applied to parameters or
variables with static storage duration. The function must take one
parameter, a pointer to a type compatible with the variable. The
return value of the function (if any) is ignored. If -fexceptions is
enabled, then cleanup_function is run during the stack unwinding that
happens during the processing of the exception. Note that the cleanup
attribute does not allow the exception to be caught, only to perform
an action. It is undefined what happens if cleanup_function does not
return normally.
I have a very simple class that looks as follows:
class CHeader
{
public:
CHeader();
~CHeader();
void SetCommand( const unsigned char cmd );
void SetFlag( const unsigned char flag );
public:
unsigned char iHeader[32];
};
void CHeader::SetCommand( const unsigned char cmd )
{
iHeader[0] = cmd;
}
void CHeader::SetFlag( const unsigned char flag )
{
iHeader[1] = flag;
}
Then, I have a method which takes a pointer to CHeader as input and looks
as follows:
void updateHeader(CHeader *Hdr)
{
unsigned char cmd = 'A';
unsigned char flag = 'B';
Hdr->SetCommand(cmd);
Hdr->SetFlag(flag);
...
}
Basically, this method simply sets some array values to a certain value.
Afterwards, I create then a pointer to an object of class CHeader and pass it to
the updateHeader function:
CHeader* hdr = new CHeader();
updateHeader(hdr);
In doing this, the program crashes as soon as it executes the Hdr->SetCommand(cmd)
line. Anyone sees the problem, any input would be really appreciated
When you run into a crash, act like a crime investigator: investigate the crime scene.
what is the information you get from your environment (access violation? any debug messages? what does the memory at *Hdr look like? ...)
Is the passed-in Hdr pointer valid?
Then use logical deduction, e.g.:
the dereferencing of Hdr causes an access violation
=> passed in Hdr points to invalid memory
=> either memory wasn't valid to start with (wrong pointer passed in), or memory was invalidated (object was deleted before passing in the pointer, or someone painted over the memory)
...
It's probably SEGFAULTing. Check the pointers.
After
your adding some source code
your comment that the thing runs on another machine
the fact that you use the term 'flag' and 'cmd' and some very small datatypes
making me assume the target machine is quite limited in capacity, I suggest testing the result of the new CHeader for validity: if the system runs out of resources, the resulting pointer will not refer to valid memory.
There is nothing wrong with the code you've provided.
Are you sure the pointer you've created is the same same address once you enter the 'updateHeader' function? Just to be sure, after new() note the address, fill the memory, sizeof(CHeader), with something you know is unique like 0XDEAD, then trace into the updateHeader function, making sure everything is equal.
Other than that, I wonder if it is an alignment issues. I know you're using 8 bit values, but try changing your array to unsigned ints or longs and see if you get the same issue. What architecture are you running this on?
Your code looks fine. The only potential issue I can see is that you have declared a CHeader constructor and destructor in your class, but do not show the implementation of either. I guess you have just omitted to show these, else the linker should have complained (if I duplicate this project in VC++6 it comes up with an 'unresolved external' error for the constructor. It should also have shown the same error for the destructor if you had a... delete hdr; ...statement in your code).
But it is actually not necessary to have an implementation for every method declared in a class unless the methods are actually going to get called (any unimplemented methods are simply ignored by the compiler/linker if never called). Of course, in the case of an object one of the constructor(s) has to be called when the object is instantiated - which is the reason the compiler will create a default constructor for you if you omit to add any constructors to your class. But it will be a serious error for your compiler to compile/link the above code without the implementation of your declared constructor, so I will really be surprised if this is the reason for your problem.
But the symptoms you describe definitely sounds like the 'hdr' pointer you are passing to the updateHeader function is invalid. The reason being that the 1st time you are dereferencing this pointer after the updateHeader function call is in the... Hdr->SetCommand(cmd); ...call (which you say crashes).
I can only think of 2 possible scenarios for this invalid pointer:
a.) You have some problem with your heap and the allocation of memory with the 'new' operator failed on creation of the 'hdr' object. Maybe you have insufficient heap space. On some embedded environments you may also need to provide 'custom' versions of the 'new' and 'delete' operator. The easiest way to check this (and you should always do) is to check the validity of the pointer after the allocation:
CHeader* hdr = new CHeader();
if(hdr) {
updateHeader(hdr);
}
else
//handle or throw exception...
The normal behaviour when 'new' fails should actually be to throw an exception - so the following code will cater for that as well:
try{
CHeader* hdr = new CHeader();
} catch(...) {
//handle or throw specific exception i.e. AfxThrowMemoryException() for MFC
}
if(hdr) {
updateHeader(hdr);
}
else
//handle or throw exception...
}
b.) You are using some older (possibly 16 bit and/or embedded) environment, where you may need to use a FAR pointer (which includes the SEGMENT address) for objects created on the heap.
I suspect that you will need to provide more details of your environment plus compiler to get any useful feedback on this problem.