我有以下功能,我在几个地方使用assert
。我想知道我在哪里以错误的方式使用断言以及为什么。第一个是错误的,因为我们不能在用户输入上使用assert。
第二个:我们可以使用assert来检查malloc
是否成功?
其余的我仍然无法弄清楚为什么。你能帮忙吗?
我想简要解释为什么assert
在给定的地方好或坏。
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <malloc.h>
#define num 10
int hh(char *);
答案 0 :(得分:3)
你定义了什么是对错,所以这取决于你,但作为一般规则你不希望你的程序逻辑在断言中(因此检查输入字符串的长度是一个很差的用法)。
请记住:断言仅在调试模式下处于活动状态,因此如果您依赖它进行错误检查(就像几乎所有示例一样),您将在发布模式中发生奇怪的事情。
即。 assert通常是一个定义,如:
/* assert() only does something if NDEBUG is NOT defined */
#ifdef NDEBUG
#else
#define assert(x) _assert(x)
#endif
有关NDEBUG
的更多信息,请参阅Where does the -DNDEBUG normally come from?你绝对不想使用断言改变流程,例如。
assert(some_function()); /* some_function only called if NDEBUG is not defined */
使用assert
检查malloc
的返回:如果未定义NDEBUG,则检查未完成,因此理论上您可以关闭并访问NULL指针。我说它不安全。请参阅Handling error checking with assert更多讨论。
让我们通过简单的“仅在调试中”过滤器逐一查看您的断言:
assert(argc==2);
/*
* If NDEBUG is defined and argc == 1 you get through,
* so anything that uses argc[1] will give undefined behavior.
* = BAD USE
*/
char *s = malloc(N);
/* 2 */
assert(s!=NULL);
scanf("%s", s
/*
* If NDEBUG is defined and malloc fails you keep going and read into
* NULL = undefined behaviour = BAD
*/
assert(strlen(s)<N);
/*
* If NDEBUG is defined keeps going even in strlen >= N.
* How bad that is depends on the code - if you are checking the size
* before putting it in a buffer, then it's bad.
* To me it is logic in the assert and so I say BAD
*/
/* 4 */
assert(!*(s+strlen(s)));
/*
* First of that's just silly code.
* If that comes to my code review you'll be removing or rewriting
* it - strlen relies on the NUL, so how can it fail?
* It is logic in the assert - If NDEBUG is set you'll keep going
* even if the condition is not met. How bad that is?
*/
/* 5 */
assert(atol(s));
/*
* Whoa. If NDEBUG is set and s = "Hello" we still keep going...
* What is atol("Hello") ?
*/
printf("%ld\n", 100000000/atol(s));
free(s);
return 0;
}
int f(char *s)
{
/* 6 */
assert(s!=NULL);
/*
* Again if NDEBUG is defined the check disappears and so if s = NULL
* then you dereference a NULL pointer which is undefined behavior
*/
return !*s;
答案 1 :(得分:2)
我希望这个答案通过努力查看断言示例的有意义使用来提供关于断言的替代视图。我否认同意谴责大部分答案的答案。
断言用于验证假设,即断言它们是真的 将断言想象为
单独查看断言示例:
assert(false)
的次数比我想象的要多。这至少使我感觉到了#Iv;我盲目地认为运行时执行永远不会在这里结束。&#34;但其他方面很奇怪,需要广泛(通常缺失)的评论解释。