www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Proper Use of Assert and Enforce

reply "Chris Pons" <cmpons gmail.com> writes:
I'm new, and trying to incorporate assert and enforce into my 
program properly.

My question revolves around, the fact that assert is only 
evaluated when using the debug switch. I read that assert throws 
a more serious exception than enforce does, is this correct?

I'm trying to use enforce in conjunction with several functions 
that initialize major components of the framework i'm using.

However, i'm concerned with the fact that my program might 
continue running, while I personally would like for it to crash, 
if the expressions i'm trying to check fail.

Here is what i'm working on:

	void InitSDL()
	{
		enforce( SDL_Init( SDL_Init_Everything ) > 0, "SDL_Init 
Failed!");

		SDL_WN_SetCaption("Test", null);

		backGround = SDL_SetVideoMode( xResolution, yResolution, 
bitsPerPixel, SDL_HWSURFACE | SDL_DOUBLEBUF);

		enforce( backGround != null, "backGround is null!");

		enforce( TTF_Init() != -1, "TTF_Init failed!" );
	}

Is it proper to use in this manner? I understand that I shouldn't 
put anything important in an assert statement, but is this ok?
Mar 13 2012
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, March 14, 2012 06:44:19 Chris Pons wrote:
 I'm new, and trying to incorporate assert and enforce into my
 program properly.
 
 My question revolves around, the fact that assert is only
 evaluated when using the debug switch.
assert has nothing to do with the debug switch. All the debug switch does is enable debug blocks. e.g. debug { writeln("A debug message."); } If you put an assertion in the debug block, then it'll only be there when you compile with -debug like any other code, but if you put it outside of the debug block, it won't be affected by -debug at all. Rather, assertions are compiled in unless you compile with the -release flag.
 I read that assert throws
 a more serious exception than enforce does, is this correct?
Not exactly. Have you used assertions in other languages? In most languages, an assertion just outright kills your program if it fails. An assertion asserts that a particular condition is true with the idea that if that condition is _not_ true, then there is a bug in your program. As such, you don't want your program to continue if it fails. It's used to verify the integrity of your program. in and out contracts use them as do invariants and unittest blocks. When an assertion fails, an AssertError is thrown, _not_ an Exception. Throwable is the base class of all exception types, and Error and Exception are derived from it. Errors are for conditions which are normally considered fatal and should almost never be caught (for instance, trying to allocate memory when you're out of memory results in an OutOfMemoryError being thrown). Unlike Exceptions, Errors can be thrown from nothrow functions, and the language does not actually guarantee that scope statements, destructors, and finally blocks will be run when an Error is thrown (though the current implementation currently does run them for Errors and there is some discussion of actually guaranteeing that it always will; regardless, catching Errors is almost always a bad idea). Exception and any types derived from Exception cannot be thrown from nothrow functions and _are_ guaranteed to trigger scope statements (aside from scope(success)), destructors, and finally blocks. They are generally meant to be recoverable and catching them is fine. They are generally used to indicate that a function is unable to properly perform its function given the current state of the program but _not_ because of a logic error. Rather, it's because of stuff like bad user input or because a file doesn't exist when it's supposed to, so opening it fails. Exceptions are used for reporting error conditions to your program. It can then either choose to catch them and handle them or let it percolate to the top of the program and kill it. But unlike Errors, it _is_ okay to catch them, and it's intended that they not indicate an unrecoverable error. So, you use an assertion when you want to guarantee something about your program and kill your program when that condition fails (indicating a bug in your program). The checks are then normally compiled out when you compile with -release. So, the idea is to use them to catch bugs during development but to not have them impede the performance of the program when you release it. The only assertions that are always left in are the ones that can be determined to be false at compile time (generally assert(0) and assert(false), though stuff like assert(1 == 0) also qualify, since their result is known at compile time). They're used when you want to guarantee that a particular line is never hit (e.g. when a switch statement is never supposed to hit its default case statement). The compiler actually inserts them at the end of non-void functions so that if the program somehow reaches the end without returning, the program will not try and continue. Exceptions, on the other hand, are _not_ used for bugs in your code, but rather error conditions which occur do to circumstances at runtime which are not controlled by your program (like bad user input). enforce is simply a way to make throwing exceptions look like assertions and save a line of code. So, instead of if(!condition) throw new Exception(msg); you do enforce(condition, msg); And if you want to throw a specific exception type, you do either enforceEx!SpecificException(condition, msg); or enforce(condition, new SpecificException(msg));
 I'm trying to use enforce in conjunction with several functions
 that initialize major components of the framework i'm using.
 
 However, i'm concerned with the fact that my program might
 continue running, while I personally would like for it to crash,
 if the expressions i'm trying to check fail.
 
 Here is what i'm working on:
 
 	void InitSDL()
 	{
 		enforce( SDL_Init( SDL_Init_Everything ) > 0, "SDL_Init
 Failed!");
 
 		SDL_WN_SetCaption("Test", null);
 
 		backGround = SDL_SetVideoMode( xResolution, yResolution,
 bitsPerPixel, SDL_HWSURFACE | SDL_DOUBLEBUF);
 
 		enforce( backGround != null, "backGround is null!");
 
 		enforce( TTF_Init() != -1, "TTF_Init failed!" );
 	}
 
 Is it proper to use in this manner? I understand that I shouldn't
 put anything important in an assert statement, but is this ok?
Shouldn't put anything important in assert statements? I'm afraid that I don't follow. Assertions are compiled out when you compile with -release, so they cannot be used when you want to guarantee that they fail even with - release or if you have code in them that must always run. So, for instance, if the foo function _had_ to be run, doing assert(foo() == expected); would be bad. You'd do immutable result = foo(); assert(result == expected); instead. The same concern does not exist with enforce, however, since it's never compiled out. As for whether assert or enforce should be used, does failure mean a bug in your program or simply that you've hit an error condition. From the looks of your code, it would probably simply be an error condition in this case, since your verifying that some initialization functions succeed. If they fail, it's not a bug in your program but rather that something else (probably outside of your control) went wrong. So, enforce is the correct choice. And if nothing calling initSDL (directly or indirectly) catches the exception, then the exception will kill your program, but it can be caught with a catch block if you choose to. If you want to _guarantee_ that the program dies if any of them fail, then you should probably create a subclass of Error (e.g. SDLInitError) and throw that, in which case, your first enforce would become enforceEx!SDLInitError(SDL_Init(SDL_Init_Everything) > 0, "SDL_Init Failed!"); Hopefully I didn't overload you too thoroughly and this at least gives you a better idea of the difference between assertions and exceptions (and therefore between assert and enforce). Assertions are for verifying the integerity of your program and failure means that your program has a bug, whereas exceptions are for reporting error conditions which do _not_ indicate a bug in your program. - Jonathan M Davis
Mar 14 2012
prev sibling next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 14.03.2012 9:44, Chris Pons wrote:
 I'm new, and trying to incorporate assert and enforce into my program
 properly.

 My question revolves around, the fact that assert is only evaluated when
 using the debug switch. I read that assert throws a more serious
 exception than enforce does, is this correct?

 I'm trying to use enforce in conjunction with several functions that
 initialize major components of the framework i'm using.

 However, i'm concerned with the fact that my program might continue
 running, while I personally would like for it to crash, if the
 expressions i'm trying to check fail.

 Here is what i'm working on:

 void InitSDL()
 {
 enforce( SDL_Init( SDL_Init_Everything ) > 0, "SDL_Init Failed!");

 SDL_WN_SetCaption("Test", null);

 backGround = SDL_SetVideoMode( xResolution, yResolution, bitsPerPixel,
 SDL_HWSURFACE | SDL_DOUBLEBUF);

 enforce( backGround != null, "backGround is null!");
A valuable trick, as enforce returns whatever passed to it or throws: backGround = enforce(SDL_SetVideoMode( xResolution, yResolution, bitsPerPixel, SDL_HWSURFACE | SDL_DOUBLEBUF), "backGround is null!");
 enforce( TTF_Init() != -1, "TTF_Init failed!" );
 }

 Is it proper to use in this manner? I understand that I shouldn't put
 anything important in an assert statement, but is this ok?
To make it real simple: - assert on stuff you know has to be true regardless of circumstances and not dependent on any possible external factors. - enforce on stuff that must be true, but in general can fail like "file not found", etc. and/or depends on proper state of external factors you can't guarantee. Also since assert stay true if program is correct (in common sense) asserts are removed from release binaries. In your case I believe enforce is justified, as capabilities of hardware are not in your direct control and the release version shouldn't segfault in the face of user. -- Dmitry Olshansky
Mar 14 2012
parent reply Spacen Jasset <spacenjasset yahoo.co.uk> writes:
On 14/03/2012 09:59, Dmitry Olshansky wrote:
...
 To make it real simple:
 - assert on stuff you know has to be true regardless of circumstances
 and not dependent on any possible external factors.
 - enforce on stuff that must be true, but in general can fail like "file
 not found", etc. and/or depends on proper state of external factors you
 can't guarantee.
Is enforce then a way of generating exceptions in an easier way rather than using some sort of "if (failure) throw" syntax? In other words, I assume it's a mechanism to help you use exceptions, and not some new semantic. ...
 A valuable trick, as enforce returns whatever passed to it or throws:

 backGround = enforce(SDL_SetVideoMode( xResolution, yResolution,
 bitsPerPixel, SDL_HWSURFACE | SDL_DOUBLEBUF), "backGround is null!");
Seems handy enough, if I understand it's purpose properly. ...
Mar 14 2012
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, March 14, 2012 20:15:16 Spacen Jasset wrote:
 Is enforce then a way of generating exceptions in an easier way rather
 than using some sort of "if (failure) throw" syntax? In other words, I
 assume it's a mechanism to help you use exceptions, and not some new
 semantic.
It is purely a way to make throwing an exception use a syntax similar to assert and save a line of code. if(!condition) throw new Exception(msg); becomes enforce(condition, msg); or enforce(condition, new Exception(msg)); It arguably adds very little, but some people really like it. - Jonathan M Davis
Mar 14 2012
next sibling parent "Chris Pons" <cmpons gmail.com> writes:
Thank you for the valuable information! The difference between 
assert and enforce is now clearer in my mind.

Also, that's a great trick with enforce.

On Thursday, 15 March 2012 at 01:08:02 UTC, Jonathan M Davis 
wrote:
 On Wednesday, March 14, 2012 20:15:16 Spacen Jasset wrote:
 Is enforce then a way of generating exceptions in an easier 
 way rather
 than using some sort of "if (failure) throw" syntax? In other 
 words, I
 assume it's a mechanism to help you use exceptions, and not 
 some new
 semantic.
It is purely a way to make throwing an exception use a syntax similar to assert and save a line of code. if(!condition) throw new Exception(msg); becomes enforce(condition, msg); or enforce(condition, new Exception(msg)); It arguably adds very little, but some people really like it. - Jonathan M Davis
Mar 14 2012
prev sibling parent reply Suliman <evermind live.ru> writes:
 It is purely a way to make throwing an exception use a syntax 
 similar to assert and save a line of code.

 if(!condition)
     throw new Exception(msg);

 becomes

 enforce(condition, msg);
So enforce is just macros on top of: if(!condition) throw new Exception(msg); ?
Feb 05 2016
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 02/05/2016 12:01 AM, Suliman wrote:
 It is purely a way to make throwing an exception use a syntax similar
 to assert and save a line of code.

 if(!condition)
     throw new Exception(msg);

 becomes

 enforce(condition, msg);
So enforce is just macros on top of: if(!condition) throw new Exception(msg); ?
Basically, yes (but of course no macros in D. :) ). T enforce(E : Throwable = Exception, T)(T value, lazy const(char)[] msg = null, string file = __FILE__, size_t line = __LINE__) if (is(typeof({ if (!value) {} }))) { if (!value) bailOut!E(file, line, msg); return value; } https://github.com/D-Programming-Language/phobos/blob/master/std/exception.d#L360 Ali
Feb 05 2016
prev sibling parent reply Minas Mina <minas_0 hotmail.co.uk> writes:
On Wednesday, 14 March 2012 at 05:44:24 UTC, Chris Pons wrote:
 I'm new, and trying to incorporate assert and enforce into my 
 program properly.

 My question revolves around, the fact that assert is only 
 evaluated when using the debug switch. I read that assert 
 throws a more serious exception than enforce does, is this 
 correct?

 I'm trying to use enforce in conjunction with several functions 
 that initialize major components of the framework i'm using.

 However, i'm concerned with the fact that my program might 
 continue running, while I personally would like for it to 
 crash, if the expressions i'm trying to check fail.

 Here is what i'm working on:

 	void InitSDL()
 	{
 		enforce( SDL_Init( SDL_Init_Everything ) > 0, "SDL_Init 
 Failed!");

 		SDL_WN_SetCaption("Test", null);

 		backGround = SDL_SetVideoMode( xResolution, yResolution, 
 bitsPerPixel, SDL_HWSURFACE | SDL_DOUBLEBUF);

 		enforce( backGround != null, "backGround is null!");

 		enforce( TTF_Init() != -1, "TTF_Init failed!" );
 	}

 Is it proper to use in this manner? I understand that I 
 shouldn't put anything important in an assert statement, but is 
 this ok?
Use assertions when a variable's value should not depend on external factors. For example, let's say you want to write a square root function. The input must be >= 0, and because this depends on external factors (e.g. user input), you must check it with `enforce()`. The output of the function must should always be >= 0 as well, but this does not depend on any external factor, so use assert for it (a negative square root is a program bug). auto sqrt(float val) { enfore(val >= 0f); float result = ... assert(result >= 0f); return result; }
Feb 05 2016
next sibling parent reply Suliman <evermind live.ru> writes:
On Friday, 5 February 2016 at 08:45:00 UTC, Minas Mina wrote:
 On Wednesday, 14 March 2012 at 05:44:24 UTC, Chris Pons wrote:
 I'm new, and trying to incorporate assert and enforce into my 
 program properly.

 My question revolves around, the fact that assert is only 
 evaluated when using the debug switch. I read that assert 
 throws a more serious exception than enforce does, is this 
 correct?

 I'm trying to use enforce in conjunction with several 
 functions that initialize major components of the framework 
 i'm using.

 However, i'm concerned with the fact that my program might 
 continue running, while I personally would like for it to 
 crash, if the expressions i'm trying to check fail.

 Here is what i'm working on:

 	void InitSDL()
 	{
 		enforce( SDL_Init( SDL_Init_Everything ) > 0, "SDL_Init 
 Failed!");

 		SDL_WN_SetCaption("Test", null);

 		backGround = SDL_SetVideoMode( xResolution, yResolution, 
 bitsPerPixel, SDL_HWSURFACE | SDL_DOUBLEBUF);

 		enforce( backGround != null, "backGround is null!");

 		enforce( TTF_Init() != -1, "TTF_Init failed!" );
 	}

 Is it proper to use in this manner? I understand that I 
 shouldn't put anything important in an assert statement, but 
 is this ok?
Use assertions when a variable's value should not depend on external factors. For example, let's say you want to write a square root function. The input must be >= 0, and because this depends on external factors (e.g. user input), you must check it with `enforce()`. The output of the function must should always be >= 0 as well, but this does not depend on any external factor, so use assert for it (a negative square root is a program bug). auto sqrt(float val) { enfore(val >= 0f); float result = ... assert(result >= 0f); return result; }
Will asserts stay after compilation in release mode?
Feb 05 2016
parent bachmeier <no spam.net> writes:
On Friday, 5 February 2016 at 09:50:43 UTC, Suliman wrote:
 Will asserts stay after compilation in release mode?
No. The only assert that remains in release mode is assert(false) or assert(0) as a way to identify that you've reached a piece of code that shouldn't be executed.
Feb 05 2016
prev sibling parent Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Friday, 5 February 2016 at 08:45:00 UTC, Minas Mina wrote:
 Use assertions when a variable's value should not depend on 
 external factors.
 For example, let's say you want to write a square root function.
 The input must be >= 0, and because this depends on external 
 factors (e.g. user input), you must check it with `enforce()`.
Or alternatively, you could place the responsibility of ensuring that precondition on the caller, in which case you'd use assert().
 The output of the function must should always be >= 0 as well, 
 but this does not depend on any external factor, so use assert 
 for it (a negative square root is a program bug).

 auto sqrt(float val)
 {
     enfore(val >= 0f);

     float result = ...
     assert(result >= 0f);
     return result;
 }
For assert()s about values coming from the caller or returned to it, you can use contracts, to make it clear that you're not only checking an internal invariant of your function: auto sqrt(float val) in { assert(val >= 0); } out(result) { if(val == 0) assert(result == 0); assert(result >= 0); } body { // use assert()s in the body only for implementation // details of your algorithm ... }
Feb 05 2016