如何使用C断言使代码更安全?

And*_*anu 4 c assert

阅读misc.与SDL开发相关的教程我发现了两个不同的例子,做了同样的事情,但是以不同的方式.从代码"安全性"和可维护性的角度来看,我想知道你认为哪两个是正确的.

在第一个例子中,程序员根本没有使用断言,但代码看起来还不错(至少在我看来):

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);
}
Run Code Online (Sandbox Code Playgroud)

在第二个例子中,程序员[其他]正在使用不同的方法,例如(代码不完全是复制粘贴):

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);
}
Run Code Online (Sandbox Code Playgroud)

是否可以在if条件(从第一个示例)中"替换"与第二个示例中的断言一样?

什么是正确的策略(如果有的话)?

Alo*_*hal 24

做替换是不行的.第二个例子是错误的,因为assert(x)被扩大到任何非调试版本(如果NDEBUG被定义).这意味着assert上面的指针检查将从发布版本中的代码中删除.这绝对是错误的.

那么,什么时候应该使用assert?它对于记录调试很有用.在某种程度上,你说,"我确信这种情况是正确的,我把它放在这里,assert以便在调试过程中捕获错误的代码,并将条件记录给代码的读者".

因此,这两个例子之间存在巨大差异.对于检查返回值的事情malloc,assert是错误的,因为无法保证它们将返回非NULL,并且如上所述,assert(x)意味着"我完全确定x是真的",而不仅仅是"如果x不是真的,那么不好".为此,一个人使用if(x) good(); else bad();控制.

SDL_Init并且SDL_SetVideoMode可以返回-1,并NULL分别.

  • assert()只应用于捕捉程序员的搞砸; 它通过撞击程序发出这样的搞砸信号,用2x4撞击程序员头部,并挥动大红旗解释搞砸了什么.这是一件非常好的事; 请参阅David Thielen的书"No Bugs",其中一章的标题是"断言世界".最终用户在程序的发布版本中可能会遇到的任何麻烦的情况都应该尽可能优雅地进行处理,当然不会让程序陷入瘫痪. (4认同)

Eli*_*sky 5

assert应该在事情​​出错时以意想不到的方式使用。通常,如果断言失败,则意味着程序中存在错误。断言用于可能刚刚发生的预期错误(即无法打开文件,未能初始化某些内容,等等)。

在您提供的示例中,assert似乎不是最合乎逻辑的解决方案。当程序无法初始化 SDL 时,以结构化的方式告诉用户它比抛出断言更有意义(这可能只会在某些系统上导致段错误)。