Andrei Ciobanu
Andrei Ciobanu

Reputation: 12838

How to use a C assert to make the code more secure?

Reading misc. tutorials related to SDL development I've found two different examples, doing the same thing, but in a different manner. I was wondering which of the two are you considering to be correct, judging from the perspective of code "security" and maintainability .

In the first example the programmer isn't using assert at all, but the code looks OK (at least for my eye):

int main(){
        SDL_Surface *screen;

        /** Initialize SDL */
        if(SDL_Init(SDL_INIT_VIDEO)!=0){
                fprintf(stderr,"Unable to initialize SDL: %s",SDL_GetError());
        }
        atexit(SDL_Quit);

        /** Sets video mode */
        screen=SDL_SetVideoMode(640,480,16,SDL_HWSURFACE);
        if(screen==NULL){
                fprintf(stderr,"Unable to set video mode: %s",SDL_GetError());
        }

        return (0);
}

In the second example the programmer [other] is using a different approach, something like (the code isn't exactly copy-paste):

int main(){
        SDL_Surface* screen;

        /** Initialize SDL */
        assert(SDL_Init(SDL_INIT_VIDEO)==0);
        atexit(SDL_Quit);

        /** Sets video mode */
        screen=SDL_SetVideoMode(640,480,16,SDL_HWSURFACE);
        assert(screen!=NULL);

        return (0);
}

Is it OK to "substitute" in the if conditions (from the first example) with asserts like in the second example ?

What's the right strategy (if there's any) ?

Upvotes: 4

Views: 7741

Answers (4)

CodingLab
CodingLab

Reputation: 1519

I use assertion for documenting preconditions and postconditions. (identifying intention of the function)

like..

double positive_division(double dividend, double divisor)
{
    //preconditions
    ASSERT(dividend>=0);
    ASSERT(divisor >0);

    double quotient = dividend/divisor;

    //postconditions    
    ASSERT(quotient>=0);
    return quotient;
}

Upvotes: 1

Alok Singhal
Alok Singhal

Reputation: 96131

It is not OK to do this substitution. The second example is wrong, because assert(x) gets expanded to nothing in non-debug builds (when NDEBUG is defined). This implies that the pointer checks in assert above are removed from the code in release builds. That is definitely wrong.

So, when should one use assert? It is useful for documenting and debugging. In a way, you're saying, "I am sure that this condition is true, and am putting it here as an assert to catch bad code during debugging, and to document the condition to the readers of the code".

So, there is a BIG difference between the two examples. For things like checking the return value of malloc, assert is wrong because there is no guarantee that they will return non-NULL, and as I have mentioned above, assert(x) means "I am completely sure x is true", and not just "If x is not true, it is bad". For this, one uses if(x) good(); else bad(); control.

SDL_Init and SDL_SetVideoMode can return -1 and NULL respectively.

Upvotes: 25

Mark Wilkins
Mark Wilkins

Reputation: 41222

Assert statements are typically used only for debug builds and will halt the program and often allow you to break into a debugger. It probably makes sense in the release build to still check for error conditions. One simple way might be like this:

assert( condition );
if ( !condition )
    handle error;

Upvotes: 3

Eli Bendersky
Eli Bendersky

Reputation: 273416

assert should be used when things go awry, in an unexpected way. Usually if an assertion fails, it means there is a bug in the program. Assertions are not used for expected errors that can just happen (i.e. failed to open a file, failed to initialize something, and so on).

In the example you presented, assert doesn't seem like the most logical solution. When the program failed to init SDL it makes more sense to tell it to the user in a structured way than to throw an assertion (which can just cause a seg-fault on some systems).

Upvotes: 5

Related Questions