我的代码有问题。注意评论。为什么?
struct node
{
struct node *left;
struct node *right;
int value;
};
static struct node root2;
int main()
{
struct node *root = (struct node *) malloc(sizeof(struct node));
assert(root->left == NULL); /* not failed. Why? */
assert(root->right == NULL); /* not failed. Why? */
assert(root2.left == NULL); /* not failed. Why? */
assert(root2.right == NULL); /* not failed. Why? */
struct node root1;
assert(root1.left == NULL); /* this failed. Why? */
assert(root1.right == NULL); /* this failed. Why? */
free(root);
return 0;
}
答案 0 :(得分:9)
使用root1,您已声明了节点的本地实例,它将在堆栈中。你没有初始化它,所以它将包含垃圾。
使用root2,您已声明了一个全局实例。默认启动代码将清除全局占用的内存。
使用root,它将存在于堆上,并将包含垃圾。无论占用的内存是否包含0,都是纯粹的运气。如果你使用calloc而不是malloc,它将为你清除内存。
答案 1 :(得分:4)
案例1:
struct node *root = (struct node *) malloc(sizeof(struct node));
assert(root->left == NULL); /* not failed. Why? */
assert(root->right == NULL); /* not failed. Why? */
这是一个侥幸,通常会失败。无法保证堆中的malloced内存将被清零 - 您需要calloc
。也就是说,我见过的许多调试运行时库将零分配内存,所以我相信这在调试模式下适合你。这可能因调试和释放模式而异。
案例2:
static struct node root2;
默认情况下,全局变量归零。我认为这是有保证的行为所以这是正确的。
案例3:
struct node root1;
assert(root1.left == NULL); /* this failed. Why? */
assert(root1.right == NULL); /* this failed. Why? */
这是在堆栈上分配并保持未初始化。再一次,我们无法保证你留下的价值,所以你会发现这会失败。
答案 2 :(得分:0)
分配新节点时,默认情况下其子节点不为NULL。他们得到垃圾值 此外,如果在包含assert.h时,断言宏被禁用,则已定义名为NDEBUG的宏。这允许编码器在调试程序时在源代码中包含许多断言调用,然后通过简单地包括如下行来禁用生产版本的所有调用:
#define NDEBUG
在其代码的开头,包含assert.h之前。
例如:
#undef NDEBUG
#include <assert.h>