woaidongmao

文章均收录自他人博客,但不喜标题前加-[转贴],因其丑陋,见谅!~
随笔 - 1469, 文章 - 0, 评论 - 661, 引用 - 0
数据加载中……

EXT_ASSERT将ASSERT与if结合在一起

ASSERT在DEBUG程序时候帮了太多太多忙,不过在ASSERT判断传入参数后,还需要if再按相同条件判断一遍,不符合规则return,这样才是正确的逻辑。但这样代码难看,且工作重复无趣,又容易出现差漏。

刚弄了个简单EXT_ASSERT宏,按我的理解应该可以解决问题,但不确定是否有漏洞,发出来大家一起瞄瞄。

 

#define RET_VOID
#define EX_ASSERT(exp, ret) {ASSERT(exp);if(!(exp))return(ret);}

 

BOOL CXXX::FunXXX(const data* p_data)
{
   EXT_ASSERT(p_data, FALSE);//---- 返回BOOL型

}

int CXXX::FunXXX(const data* p_data)
{
   EXT_ASSERT(p_data, -1);//---- 返回int型

}

const retdata* CXXX::FunXXX(const data* p_data)
{
    EXT_ASSERT(p_data, NULL);//---- 返回NULL指针

}

retdata CXXX::FunXXX(const data* p_data)
{
    EXT_ASSERT(p_data, retdata());//---- 返回空对象

}

void CXXX::FunXXX(const data* p_data)
{
    EXT_ASSERT(p_data, RET_VOID);//---- 仅仅return

}

posted on 2008-11-03 23:34 肥仔 阅读(2874) 评论(15)  编辑 收藏 引用 所属分类: C++ 基础

评论

# re: EXT_ASSERT将ASSERT与if结合在一起  回复  更多评论   

哥们儿,如果你是说MFC里的ASSERT的话(看你的类命名风格,估计是吧),在retail build里,ASSERT是完全不会被放到代码里的。你这样用ASSERT,把ASSERT和if条件绑在一起就等于把处理错误的断言和正常程序逻辑绑在了一起,不是一个好的设计。如果一定要这么干,也该是绑VERIFY,至少在retail build里VERIFY里的逻辑还会被执行。

ASSERT应该拿来断言程序正常执行完全不可能出现的错误(这些错误会在debug build里出现是因为当前程序还不完善),在正常逻辑中,他们是不应该用程序逻辑去handle的错误,所以一句ASSERT够了。
2008-11-04 05:27 | www.helpsoff.com.cn

# re: EXT_ASSERT将ASSERT与if结合在一起  回复  更多评论   

@www.helpsoff.com.cn
我在Imperfect C++中看到过相同的言论。
不过我的应用是,常常用ASSERT检测参数的合法性,ASSERT之后,当然还要if一把了,对于ASSERT和if不要放在一起这种观点,我不是很认同,我觉得放在一起很好用的。

另外,在Release下,ASSERT没了,但是if留下了,这是需要的效果。
2008-11-04 10:45 | 肥仔

# re: EXT_ASSERT将ASSERT与if结合在一起  回复  更多评论   

我不会这么用,断言的目的去那了。
2008-11-04 11:30 | Touchsoft

# re: EXT_ASSERT将ASSERT与if结合在一起  回复  更多评论   

@肥仔
哥们儿,你还是没理解,ASSERT的不是拿来干这个的。你爱怎样玩就怎样玩吧,反正自己的代码自己维护,其他人的意见听不听在你。
2008-11-04 12:29 | www.helpsoff.com.cn

# re: EXT_ASSERT将ASSERT与if结合在一起  回复  更多评论   

@www.helpsoff.com.cn
谢谢你的意见,但是不采纳。原因有3点经历:

1、ASSERT判断函数参数合法性,调试时会帮了很大的忙;
2、if判段函数参数合法性,是健壮性的一部分;
3、ASSERT和if 合在一起,不觉得有任何不妥,且ASSERT不出现在Release中,这正是需要的。

可能涉及到的一个争论是,检测参数合法形是调用者,还是被调用者的责任?
C/C++的主流是调用者保证参数的合法性,被调用者不检测参数合法性,这就是为什么认为,只要ASSERT,不需要if了。
strcpy(szBuf, NULL)之所以让一个程序崩溃也是这个原因,但是为什么要让它崩溃?能够不崩溃,继续执行岂不是更好吗?
2008-11-04 13:44 | 肥仔

# re: EXT_ASSERT将ASSERT与if结合在一起  回复  更多评论   

1) 没人否认ASSERT的用处;
2) 需要if判断处理的参数和用ASSERT断言的不合法参数,不应属于一个范畴,不应该混合在一起处理;
3) 代码不管怎么写在没遇到问题前都不会有什么不妥,自己觉得好就好吧。

你当然可以去写一个万能的strcpy,但是如何能保证你的strcpy是真正的“万能”的呢?不崩溃继续执行倒是没问题,但是出问题的真正根源在哪里呢,你这样做不就掩盖了问题吗?应该做的是出现这样的问题时,能有用且有效的指出错误,而不是做garbage in, garbage out。

设计代码,不去扯那些玩得出花花的设计模式,有些很基本很直白的原则,比如说“garbage in, garbage out”,比如高内聚/低耦合...说多了也没意思,楼主爱怎么玩怎么玩,大家都是这么过来的,其中的东西自己去体会了。
2008-11-04 15:35 | www.helpsoff.com.cn

# re: EXT_ASSERT将ASSERT与if结合在一起  回复  更多评论   

@www.helpsoff.com.cn
程序以外,人生很多地方都需要与别人探讨,对于不合己见者,请不必太在怀,更没必要带着情绪和语气,摆出姿态。这样才能赢得更多的合作,我想我的这几句话还算中肯。
2008-11-04 16:32 | 肥仔

# re: EXT_ASSERT将ASSERT与if结合在一起  回复  更多评论   

学习。
2008-11-04 18:28 | SpringSnow

# re: EXT_ASSERT将ASSERT与if结合在一起  回复  更多评论   

assert跟if的行为不同,为什么要做一些debug和release行为不同的程序出来,有意义?
2008-11-04 23:36 | 陈梓瀚(vczh)

# re: EXT_ASSERT将ASSERT与if结合在一起  回复  更多评论   

晕菜。算了。
2008-11-05 06:28 | 矩阵操作

# re: EXT_ASSERT将ASSERT与if结合在一起  回复  更多评论   

@陈梓瀚(vczh)
Debug会有ASSERT,也会有if
Release没有ASSERT,有if.
没有不同行为
2008-11-05 11:13 | 肥仔

# re: EXT_ASSERT将ASSERT与if结合在一起  回复  更多评论   

我觉得有的时候的确需要断言和if结合在一起。在release中断言没了,如果没有if,就没有了对错误的处理
2008-11-05 13:22 | wzcsoft

# re: EXT_ASSERT将ASSERT与if结合在一起[未登录]  回复  更多评论   

assert是确保不应该发生的事情不要发生,而if则是可能发生。在大多数的情况下assert后面其实并不需要if,不知道我说的你有没有理解。在release模式下如果执行If,那么后面的代码就不会执行,这个时候错误处理就不好弄了。所以建议还是分开,不要这么写。个人经验,仅供参考。
2008-11-05 19:00 | megax

# re: EXT_ASSERT将ASSERT与if结合在一起  回复  更多评论   

@megax
我理解你所说的和你的建议,书里面也是如你所说的。CRT,MFC也是从来ASSERT后面,没有if,没有参数合法性检查。

但是这种形式给我带来过很多麻烦,请听听我的理解:
以strcpy举例(在这个函数上没有栽过跟头的程序员,不是个合格的程序员),strcpy(buf, NULL);将导致程序崩溃,为何?因为ASSERT后面没有带if,也就是没有对参数合法性进行校验。

我理解的,strcpy这样行为的后果是:把一个业务逻辑的bug,转成耦合了平台底层的bug。

1、strcpy(buf, NULL),逻辑上的bug应该是buf没有拷贝任何数据,如果作了参数检查,那么这个bug的最终表现形式是逻辑上的:buf没有出现应该出现的数据;
2、因为没有参数检查,程序崩溃了,那么这个bug就耦合上了平台的内存管理规则,内存访问违规了,程序崩溃是这个bug的表现,这种表现形式和逻辑上应该出现的结果有联系吗?没有;
3、检测与修正业务逻辑的bug的难度远远小于与平台耦合的bug,可以依赖于日志,模拟重现等许多方法。但是比如程序崩溃这样耦合了平台的bug,如果不是到了一定程度的程序员,让他去调查一个服务器运行几天down掉的原因,那将难于上青天。
4、若写服务器,你将体会到,偶尔业务逻辑执行不正确不是什么大事情,只是一个业务逻辑上的bug而已,真正的大事情是服务器时不时给你来个crash down。很多情况的发生都是因为参数错误不合法,到了ntdll或者其他系统dll里面崩掉了。

C/C++库里面,成千上万的函数,你需要一个个了解他们传递什么样的参数才是合法,要保证不犯错误,是不可能的,但是一旦犯错,它给你来一刀,可不是很好受,为什么如此?原因就是ASSERT后面没有if。

所以,吃过亏后,我一般都在参数的ASSERT后面,带上一个if,个人觉得很受用。

2008-11-05 22:19 | 肥仔

# re: EXT_ASSERT将ASSERT与if结合在一起  回复  更多评论   

楼主真是有性格,二楼的兄弟的意见你竟然一点听不进去。
你的做法将会隐藏很多的BUG,不是你的方法,而是你的思维会让你付出代价的。
strcpy不载跟头的就不是好程序员?我只用过strncpy。
崩溃是我最不怕的,比较害怕的是有时正确有时错误,隐藏的BUG才是致命的。
这种方法只在特定情况下好用
2009-07-19 11:39 | km

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理