動いてるように見えて動かない

連結リストから、検索してヒットしたノードを削除するために、カーソルが示すノードを消す関数を書いてみた。面倒に思えたけど、その面倒だなという感覚はポインタの記法に対する不慣れから来るだけという気がする。やるべきことは単純。

void DeleteNode(List *list) {
  Node *pre, *node = list->head;

  if (node == NULL) {
    return;
  } else if (node->next == NULL) {
    InitList(list);
    free(node);
  } else {
    while (1) {
      pre = node;
      node = node->next;
      if (node == list->cursor) {
	pre->next = node->next;
	list->cursor = node->next;
	free(node);
	break;
      }
    }
  }
}

やるべきことは単純と言いつつ、ちゃんと動かない。途中のノードはうまく消せるけど、どうもノード数が減っていったとき、ifの2個目のブロックでsegmentation faultが出てる。わからんなぁ。

#include <stdio.h>
#include <stdlib.h>

// Data structure definition

typedef struct {
  int x;
  int y;
  int size;
} Data;

typedef struct __node {
  Data data;
  struct __node *next;
} Node;

typedef struct {
  Node *head;
  Node *cursor;
} List;

// initialize and set objects

void InitList(List *list) {
  list->head = NULL;
  list->cursor = NULL;
}

Node *AllocNode(void) {
  return malloc(sizeof(Node));
}

void SetNode(Node *node, Data *data, Node *next) {
  node->data = *data;
  node->next = next;
}

// Print the list given

void PrintData(Data data) {
  printf("x, y: %d, %d\n", data.x, data.y);
  printf("size: %d\n", data.size);
}

void PrintList(List *list) {
  if (list->head == NULL)
    puts("The list is empty");
  else {
    Node *node;
    for (node = list->head; node != NULL; node = node->next)
      PrintData(node->data);
  }
}

// list operations

void InsertHead(List *list, Data *data) {
  Node *node = list->head;
  list->head = list->cursor = AllocNode();
  SetNode(list->head, data, node);
}

void AppendTail(List *list, Data *data) {
  if (list->head == NULL) {
    InsertHead(list, data);
  } else {
    Node *node;
    for (node = list->head; node->next != NULL; node = node->next);

    node->next = list->cursor = AllocNode();
    SetNode(node->next, data, NULL);
  }
}

void DeleteNode(List *list) {
  Node *pre, *node = list->head;

  if (node == NULL) {
    return;
  } else if (node->next == NULL) {
    InitList(list);
    free(node);
  } else {
    while (1) {
      pre = node;
      node = node->next;
      if (node == list->cursor) {
	pre->next = node->next;
	list->cursor = node->next;
	free(node);
	break;
      }
    }
  }
}

void SearchSize(List *list, int size) {
  if (list->head == NULL)
    return;
  else {
    Node *node;
    for (node = list->head; node != NULL; node = node->next) {
      if (node->data.size == size) {
	list->cursor = node;
	break;
      }
    }
  }
}

// ------------------------------

int main(void) {
  List list;
  Data data;
  int s, i;

  InitList(&list);

  data.x = 320; data.y = 240;
  for (s = 100; s < 130; s += 5) {
    data.size = s;
    InsertHead(&list, &data);
  }
  data.x += 10; data.y += 10;
  AppendTail(&list, &data);

  PrintList(&list);

  SearchSize(&list, 115);
  printf("\nfound this\n");
  PrintData(list.cursor->data);
  printf("\ndelete the found node\n");
  DeleteNode(&list);
  printf("\nand the new list is\n");
  PrintList(&list);

  for (i = 1; i <= 5; i++) {
    printf("\ndelete the node at the cursor\n");
    DeleteNode(&list);
    printf("\nand the new list is\n");
    PrintList(&list);
  }
}