提问人: 提问时间:8/24/2022 更新时间:8/24/2022 访问量:90
链表搜索不起作用(SIGBUS 错误和内存泄漏)
Linked List Search not working (SIGBUS error and memory leak)
问:
我制作了一个实现链表的 C 程序,但它不起作用......我实现的所有内容都取自网站或 stackoverflow,它似乎对每个人都有效,但仍然对我不起作用。
每次我运行程序(它在 STDIN 中输入一系列单词,一个用于行)它给我并调试它时,它似乎卡在搜索功能中的行中......我哪里错了?我想有一些与指针有关的东西,但我不明白是什么。
程序开始工作并打印一些东西,然后中断,值没有,因为它说。Process finished with exit code 138 (interrupted by signal 10: SIGBUS)
if (strcmp(var->word, searched) == 0)
temp
word
read memory from 0x6c62430000600000 failed (0 of 1 bytes read)
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node{
char* word;
struct node* next;
};
int search(struct node** head, char* searched);
void Print(struct node* head);
void Free_All(struct node* head);
void Insert(struct node** head, char* word);
void Delete(struct node* head, char* to_delete);
int Count(struct node* head);
int main() {
static struct node *head = NULL;
int temp;
char word[20];
for (;;) {
temp = scanf("%s", word);
if (strcmp(word, "Print") == 0) {
Print(head);
}
else if (strcmp(word, "Stop") == 0) {
break;
}
else if (temp == EOF) {
Free_All(head);
return 0;
}
else {
Insert(&head, word);
}
}
scanf("%s", word);
int found = search(&head, word);
if (found == 0) {
printf("!! ERROR !!");
return 1;
}
else {
char to_delete[15];
scanf("%s", to_delete);
Delete(head,to_delete);
// DO OTHER STUFF
}
int count = Count(head);
printf("Remaining nodes: %d",count);
Free_All(head);
}
int search(struct node** head, char* searched) {
struct node* var = *head;
while (var != NULL) {
if (strcmp(var->word, searched) == 0)
return 1;
var = var->next;
}
return 0;
}
void Print(struct node* head){
struct node* temp = head;
while (temp) {
printf("%s \n", temp->word);
temp = temp->next;
}
}
void Free_All(struct node* head){
struct node* temp;
temp = head;
while( temp != NULL ){
head= head->next;
free(temp);
temp = head;
}
}
void Insert(struct node** head, char* word)
{
// Create new node
struct node* new_node = (struct node*)malloc(sizeof(struct node));
new_node->word = malloc(strlen(word)+1);
new_node->word = strcpy(new_node->word,word);
new_node->next = NULL;
if (*head== NULL || strcmp((*head)->word, new_node->word) >= 0) {
new_node->next = *head;
*head= new_node;
}
else {
struct node* temp = *head;
temp = *head;
while (temp->next != NULL && strcmp(temp->next->word, new_node->word) < 0) {
temp = temp->next;
}
new_node->next = temp->next;
temp->next = new_node;
}
}
void Delete(struct node* head, char* to_delete) {
struct node *temp = head;
struct node *prev = NULL;
while(temp != NULL){
if(strcmp(temp->word, to_delete) == 0)
{
if(prev == NULL){
head = head->next;
free(temp);
return;
}
else{
prev->next = temp->next;
free(temp);
return;
}
}
prev = temp;
temp = temp->next;
}
}
int Count(struct node* head){
int counter = 0;
struct node* var = head;
while (var != NULL)
{
counter++;
var = var->next;
}
return counter;
}
编辑:解决了主要的错别字
答:
该函数按值接受指向头节点的指针Delete
void Delete(struct node* head, char* to_delete);
因此,该函数处理在 main 中声明的指针头值的副本
static struct node *head = NULL;
更改 main 中声明的指针头值的副本会使原始指针的值保持不变。
您需要通过指向指针的指针通过引用传递指针。
例如,可以按以下方式声明和定义函数。
int Delete( struct node **head, const char *to_delete )
{
while ( *head != NULL && strcmp( ( *head )->word, to_delete ) != 0 )
{
head = &( *head )->next;
}
int success = *head != NULL;
if ( success )
{
struct node *tmp = *head;
*head = ( *head )->next;
free( tmp );
}
return success;
}
注意这个for循环
for (;;) {
temp = scanf("%s", word);
if (strcmp(word, "Print") == 0) {
Print(head);
}
if (strcmp(word, "Stop") == 0) {
break;
} else if (temp == EOF) {
Free_All(head);
return 0;
} else {
Insert(&head, word);
}
}
逻辑错误。例如,如果用户将输入字符串,那么除了调用函数之外,还将调用该函数"Print"
Print
Insert(&head, word);
而且这个功能实际上并没有释放所有人。它不会释放数据成员指向的字符数组。Free_All
word
void Free_All(struct node* head){
struct node* temp;
temp = head;
while( temp != NULL ){
head= head->next;
free(temp);
temp = head;
}
}
该函数还应通过引用接受指向头节点的指针。它看起来像这样
void Free_All( struct node **head )
{
while ( *head != NULL )
{
free( ( *head )->word );
struct node *tmp = *head;
*head = ( *head )->next;
free( tmp );
}
}
评论
SIGABRT (signal SIGABRT)
我没有时间或耐心逐行检查您的代码出了什么问题。现在,删除列表中的第一项不会影响 'main()' 中的“head”指针,因此使用该指针指向 or 是未定义的行为。Count()
FreeAll()
下面是一些代码。使用铅笔和纸来跟踪正在使用的极少数变量,以及指针指向的位置。
void Print( struct node *p ) {
for( ; p; p = p->next )
printf( "%s ", p->word );
putchar( '\n' );
}
void Insert( struct node **head, char *word ) {
// assemble new node
struct node *nn = (struct node*)malloc( sizeof node );
nn->word = (char*)malloc( strlen( word ) + 1 );
nn->word = strcpy( nn->word, word );
nn->next = NULL;
// find insertion point
struct node *pPrev = NULL;
struct node *pThis = *head;
while( pThis && strcmp( word, pThis->word ) >= 0 )
pPrev = pThis, pThis = pThis->next;
// insert into (possibly empty) list
if( pThis ) nn->next = pThis;
if( pPrev ) pPrev->next = nn;
if( pThis == *head ) *head = nn; // new head?
}
void Delete( struct node **head, char *word ) {
struct node *pPrev = NULL;
for( struct node *pThis = *head; pThis; pPrev = pThis, pThis = pThis->next ) {
int res = strcmp( pThis->word, word );
if( res < 0 ) // not found yet
continue;
if( res > 0 ) // gone beyond, so not present
break;
// Found!
if( pPrev ) pPrev->next = pThis->next; // excise from list
if( pThis == *head ) *head = pThis->next; // change head??
free( pThis->word ); // release memory
free( pThis ); // release memory
break;
}
}
int main() {
struct node *head = NULL;
char word[20];
printf( "Entry phase:\n" );
for( ;; ) {
Print( head );
scanf( "%s", word );
if( strcmp( word, "Stop" ) == 0 )
break;
Insert( &head, word );
}
printf( "Delete phase:\n" );
while( head ) {
Print( head );
scanf( "%s", word );
if( strcmp( word, "Stop" ) == 0 )
break;
Delete( &head, word );
}
return 0;
}
输出:
Entry phase:
baker
baker
delta
baker delta
able
able baker delta
epsilon
able baker delta epsilon
charlie
able baker charlie delta epsilon
Stop
Delete phase:
able baker charlie delta epsilon
able
baker charlie delta epsilon
epsilon
baker charlie delta
charlie
baker delta
baker
delta
delta
{ program halts }
评论
Insert()
Print
Stop
else
Delete( )
接收头指针的 COPY,而不是头指针的地址。如果删除第一个条目,则 head in 指向无效内存。Insert() 也好不到哪里去......拿一张纸和笔,画出你想要发生的事情......S-L-O-W-L-Y...main()