typedef struct node
{
struct node *leftChild, *rightChild;
int value;
} bst;
void insert(bst* b, int i)
{
b=malloc(sizeof(b));
b->value=i;
b->leftChild = NULL;
b->rightChild = NULL;
printf("[%i]",b->value);
return;
}
main()
{
bst* b;
insert(b,5);
printf("[%i]",b->value);
}
第二个printf会导致分段错误,将其注释掉它可以正常工作。我在这里做错了什么(忽略函数名的含义,即插入是bst的插入函数)?不应该在插入函数之外的设置中持续存在吗?
答案 0 :(得分:4)
您需要通过引用传递指针以更改其指向的位置。
// just add this & here in the function definition.
// That's the only change in all your code (for c++)
void insert(bst * &b, int i)
或者在C中,指针指针
void insert(bst ** b, int i)
{
*b=malloc(sizeof(*b));
(*b)->value=i;
(*b)->leftChild = NULL;
(*b)->rightChild = NULL;
printf("[%i]",(*b)->value);
return;
}
请注意取消引用指针指针的更改。
当您调用此功能时,您需要获取bst *的地址:
insert(&b,5);
答案 1 :(得分:2)
问题是b
中的main
指向无效的内存。 b
不会被insert
更改,因为insert使用指针的副本。你必须有选择来解决这个问题:
因为第一个更难阅读(并理解),我更喜欢第二个。但这取决于你选择的变体。
insert
之前的内存分配:
typedef struct node
{
struct node *leftChild, *rightChild;
int value;
} bst;
void insert(bst* b, int i)
{
// No malloc here
b->value=i;
b->leftChild = NULL;
b->rightChild = NULL;
printf("[%i]",b->value);
return;
}
main()
{
bst* b = (bst *)malloc(sizeof(bst)); // This line has changed
insert(b,5);
printf("[%i]",b->value);
}
带有双指针的变体:
typedef struct node
{
struct node *leftChild, *rightChild;
int value;
} bst;
void insert(bst** b, int i)
{
*b = (bst *)malloc(sizeof(bst)); // This line has changed
(*b)->value=i;
(*b)->leftChild = NULL;
(*b)->rightChild = NULL;
printf("[%i]", (*b)->value);
return;
}
main()
{
bst* b;
insert(&b,5); // Now b is changed
printf("[%i]",b->value);
}
旁注1 :你的malloc()也不正确 - 你应该使用sizeof(bst)
而不是sizeof(b)
作为大小。这是因为sizeof(b) == sizeof(bst *) == size of an address
,几乎肯定不是你想要的。
旁注2 :不要忘记在最后调用free(b)
以避免内存泄漏。
旁注3 :检查malloc()
是否未返回NULL
。一个罕见的案例,但一个好的计划应该期待。
答案 2 :(得分:2)
由于C为参数传递值,因此insert()
中引用的指针是原始b
的副本。内存分配给函数内部的变量b,但不分配给main()
函数中的变量。
例如。
# In main
b<main> = 0xOrigLoc
b<insert> = undefined
# In insert (before malloc)
b<main> = 0xOrigLoc
b<insert> = 0xOrigLoc
# After Malloc
b<main> = 0xOrigLoc
b<insert> = 0xNewLoc
请注意b<main>
如何保持不变。你只是在函数内部调整了b的副本。
解决方案是使用指针指针,如前面的解决方案所述。
答案 3 :(得分:2)
不是更改值,而是返回b的新值
bst* insert(bst* b, int i)
{
if (b == NULL)
{
bst* result = (bst*)malloc(sizeof(bst));
result->value=i;
result->leftChild = NULL;
result->rightChild = NULL;
printf("[%i]",b->value);
return result;
}
if (i < b->value)
b->left = insert(b->left, i);
else
b->right = insert(b->right, i);
return b;
}
int main()
{
bst* b = NULL; // Initialise it to empty.
b = insert(b,5);
printf("[%i]",b->value);
}
答案 4 :(得分:1)
一个问题是你没有对你的指针进行类型转换。
该行:
b=malloc(sizeof(b));
应该是:
b=(bst*)malloc(sizeof(b));
当我在gcc中编译它时,你的代码给我一个错误。
这是如何识别和修复未来的错误:
在GDB中进行测试:
完整代码:
#include <malloc.h>
#include <stdio.h>
typedef struct node
{
struct node *leftChild, *rightChild;
int value;
} bst;
void insert(bst* b, int i)
{
b=(bst*)malloc(sizeof(b));
b->value=i;
b->leftChild = NULL;
b->rightChild = NULL;
printf("[%i]",b->value);
return;
}
main()
{
bst* b;
insert(b,5);
printf("[%i]",b->value);
}
编译
%g ++ -g main.cc
随着
%gdb a.out
GDB命令:
b main.cc:211
run
print b
(output is: 0x0)
step
step
print b
(output is: 0x4f60010)
step
step
step
step
step
print b
(output is: 0x0)
quit
这清楚地表明当函数离开其范围时,您的变量将被释放。
将代码更改为:
#include <malloc.h>
#include <stdio.h>
typedef struct node
{
struct node *leftChild, *rightChild;
int value;
} bst;
void insert(bst* b, int i)
{
b->value=i;
b->leftChild = NULL;
b->rightChild = NULL;
printf("[%i]",b->value);
return;
}
main()
{
bst* b;
b=(bst*)malloc(sizeof(bst));
insert(b,5);
printf("[%i]",b->value);
free(b);
}
并使用以下命令重新运行gdb:
b main.cc:21
run
s
(short for step)
print b
(output: 0x1aab010)
s
s
s
s
s
s
print b
(output: 0x1aab010)
您的问题显然是分配的范围。将分配移至主要修复此问题。
你的程序现在可以使用了!
这可以让您深入了解如何使用调试器来解决这些类型的简单错误。
修改强>:
正如一个操作指出的那样,你的根本问题是传递给c中函数的指针被视为本地对象,因此当你退出函数时,任何分配给单个指针的内存都会被丢弃在bitbucket中。
双指针允许您在函数内实际分配,您必须小心地根据需要取消引用它们。所以你的工作代码也可以是:
#include <malloc.h>
#include <stdio.h>
typedef struct node
{
struct node *leftChild, *rightChild;
int value;
} bst;
void insert(bst** b, int i)
{
(*b)=(bst*)malloc(sizeof(bst));
(*b)->value=i;
(*b)->leftChild = NULL;
(*b)->rightChild = NULL;
printf("[%i]",(*b)->value);
return;
}
main()
{
bst* b;
insert(&b,5);
printf("[%i]",b->value);
free(b);
}
答案 5 :(得分:-1)
bst * b;声明一个指针......但不分配实际的结构。 分配并初始化b,您将进入下一步。
这只是一种风格讨论,但你的主要应该看起来像这样。
main()
{
bst *b;
b = (bst*)malloc(sizeof(bst));
/* more initialization */
insert(b, 5);
free(b);
}
或者像这样
main()
{
bst *b;
bst_new(&b);
insert(b, 5);
bst_free(&b);
}