我对C很陌生,并且很难掌握对指针的充分理解 当前的任务是清除struct Commands中的每个数组(结构显示在底部) 希望有人可以识别出可怕的错误,例如多次释放某些东西。我知道我的代码可能看起来很可怕,但感谢你花时间去看它 我目前正在尝试清除所有内容:
void clear_commands(Commands *commands) {
Command *compile, *test, *temp;
if (commands != NULL) {
compile = commands->compile;
while (compile != NULL) {
temp = compile;
compile = compile->next;
free(temp);
}
test = commands->test;
while (test != NULL) {
temp = test;
test = test->next;
free(temp);
}
free(commands);
commands = NULL;
}
}
这些是typedef:
typedef struct Command{
char *command;
struct Command *next;
} Command;
typedef struct {
Command *test;
Command *compile;
} Commands;
ADDED:read_commands
Commands read_commands(const char *compile_cmds, const char *test_cmds) {
FILE *f;
Commands *commands = malloc(sizeof(Commands));
Command *compile, *test;
char temp[257];
if (compile_cmds == NULL || test_cmds == NULL)
exit(0);
compile = malloc(sizeof(Command));
test = malloc(sizeof(Command));
commands->compile = compile;
commands->test = test;
f = fopen(compile_cmds,"r");
if (f != NULL)
while(!feof(f)) {
if(fgets(temp, 257, f) != NULL) {
compile = malloc(sizeof(Command));
compile->command = malloc(strlen(temp) + 1);
strcpy(compile->command, temp);
compile->next = malloc(sizeof(Command));
compile = compile->next;
}
}
fclose(f);
...
return *commands;
}
答案 0 :(得分:1)
free(commands->compile);
和free(commands->test);
不是必需的,您可以在第一个循环中释放它们
clear_commands
很好,问题出在read_commands
commands->compile = NULL; /* use malloc here */
commands->test = NULL; /* and here */
compile = commands->compile; /* otherwise you are giving NULL pointer variable to compile */
test = commands->test; /* Same here */
f = fopen(compile_cmds,"r");
if (f != NULL)
while(!feof(f)) {
if(fgets(temp, 257, f) != NULL) {
compile = malloc(sizeof(Command)); /* this is not necessary */
compile->command = malloc(strlen(temp) + 1);
strcpy(compile->command, temp);
compile->next = NULL; /* use malloc here */
compile = compile->next; /* if not, compile is NULL again */
}
}
fclose(f);
/*after this add:*/
if (compile == commands->compile) {
commands->compile = NULL;
}
free(compile);
compile = NULL;
与test_cmds相同的事情
答案 1 :(得分:1)
我在read_commands中看到了一些事情,这些事情并不完全正确!
您在代码开头设置时commands->compile
和commands->test
始终为NULL!创建新变量compile = commands->compile
然后使用compile
运行所有代码并不意味着您的原始commands->compile
也将被修改。因此,在您的第一个fclose(f);
compiles->next
仍然是NULL
之后,由于您没有更改它,您更改了另一个变量compile
。
即使你可能正在改变commands->test
,compile->next
或test->next
,这也是错误的。
您需要了解当您在first
指针变量中复制second
指针的值,并且更改second
指向的变量的值时,使用first
访问时的值也会显示更改。
示例::
int a = 10, *b, *c;
b = &a;
c = a;
*c = 30; // a gets changed
这并不意味着如果您更改second
本身,也会更改first
指向的值。
示例::
int a = 10, *b, *c, *d, e = 30;
b = &a;
d = &e;
c = b;
c = d; //This does not change a
这是您在read_commands
代码中尝试执行的操作。我想你可以从中得到一个想法并理解你的错误!
编辑::
更正代码的一部分::
Command *prev = NULL;
f = fopen(compile_cmds,"r");
if (f != NULL)
while(!feof(f)) {
if(fgets(temp, 257, f) != NULL) {
Command *var = malloc(sizeof(Command));
var->command = malloc(strlen(temp) + 1);
var->next = NULL;
strcpy(var->command, temp);
if(prev == NULL) {
compile = var;
prev = compile;
} else {
prev->next = var;
prev = var;
}
}
}
commands->compile = compile;
答案 2 :(得分:1)
Commands read_commands(const char *compile_cmds, const char *test_cmds) {
FILE *f;
Commands *commands = malloc(sizeof(Commands));
Command *compile, *test;
char temp[257];
if (compile_cmds == NULL || test_cmds == NULL)
exit(0);
compile = malloc(sizeof(Command));
test = malloc(sizeof(Command));
commands->compile = compile;
commands->test = test;
f = fopen(compile_cmds,"r");
if (f != NULL)
while(!feof(f)) {
if(fgets(temp, 257, f) != NULL) {
compile->command = malloc(strlen(temp) + 1);
strcpy(compile->command, temp);
compile->next = malloc(sizeof(Command));
compile = compile->next;
}
}
fclose(f);
...
return *commands;
}
答案 3 :(得分:0)
在这种情况下,递归解决方案是最简单,最容易理解的解决方案;只要你的列表不长,堆栈就会因递归深度而溢出:
void clear_command_list( Command* cmd_list )
{
// If this node exists...
if( cmd_list != NULL )
{
// Clear the tail list
clear_command_list( cmd_list->next ) ;
// Free command string in this node
free( cmd_list.command ) ;
cmd_list.command = NULL ;
// Free Command node
free( cmd_list ) ;
cmd_list = NULL ;
}
}
void clear_commands(Commands *commands)
{
// Delete test list
clear_command_list( commands->test ) ;
// Delete compile list
clear_command_list( commands->compile ) ;
// Delete the Commands header
free( commands ) ;
commands = NULL ;
}
请注意,如果错误地再次释放指针,则在free()
之后将指针设置为NULL可防止堆损坏。
每个列表可以被视为一个节点,后跟一个较小的列表。 clear_command_list()
函数使用“较小”列表调用自身,然后删除头数据。递归变得越来越深,直到找到终止的NULL节点,递归展开从末尾向后删除每个节点。
即使您迭代地执行此操作,可以删除clear_command_list()
和compile
列表的单独test
函数也是有意义的,而不是使用不同的变量重复相同的代码 - 这是维护重并且容易出错。正确一次并重新使用它。结构与上述相同(且clear_commands()
函数相同,只需更改clear_command_list()
:
void clear_command_list( Command* cmd_list )
{
Command* next = cmd_list ;
// For each lode in list
while( next != NULL )
{
Command* node = next ;
next = node->next ;
// Free command string in this node
free( node->command ) ;
node->command = NULL ;
// Free Command node
free( node ) ;
node = NULL ;
}
}