Return 来自函数的指针,然后释放指针

Return a pointer from a function, then free the pointer

我正在尝试从命令行 argv[] 处理多个名称,然后添加或删除以“+”或“-”开头的所述名称。 IE +bill +ted -ted 将添加 bill 和 ted,然后删除 ted。我可以毫无问题地将名称添加到此列表,但我的 removeNode() 函数调用导致分段错误。在我的 main() 中,当我转到要删除的进程名称时,我将 char * name 设置为等于 removeNode() 的 return 指针,这应该是来自被释放节点的字符串。 return 这个指针的正确方法是什么,这样我就可以从命令行中删除我引用的名称?我还包含了我的插入功能。

int insert(struct node ** head, char * name) {
    struct node * newNode = (struct node * ) malloc(sizeof(struct node));
    newNode -> data = name;
    newNode -> next = NULL;
    struct node * current = * head;
    if ( * head == NULL) {
        * head = newNode;
        return 1;
    }
    while (current -> next != NULL) {
        current = current -> next;
    }
    current -> next = newNode;
    return 1;
}

char * removeNode(struct node ** head, char * name) {
    struct node * current = * head;
    struct node * previous;

    if (current == NULL) {
        return "error0";
    }

    if (strcmp(current -> data, name) == 0) {
        char * data = current -> data;
        * head = current -> next;
        free(current);
        printf("Removed %s \n", name);
        return data;
    }
    while (current != NULL) {
        previous = current;
        current = current -> next;
        if (strcmp(current -> data, name) == 0) {
            char * data = current -> data;
            previous -> next = current -> next;
            free(current);
            printf("Removed %s \n", name);
            return data;
        }
    }
    return "error0";
}

int main(int argc, char * argv[]) {
    printf("Author : Torin Costales \n");
    struct node * head = NULL;
    for (int x = 1; x < argc; x++) {
        if (argv[x][0] == '+') {
            char * name = malloc((strlen(argv[x] + 1) + 1));
            if (name == NULL) return EXIT_FAILURE;
            strcpy(name, argv[x]);
            printf("adding %s \n", name);
            insert( & head, name);
            printf("List: ");
            printList( & head);
        } else if (argv[x][0] == '-') {
            printf("removing %s \n", argv[x] + 1);
            char * name = removeNode( & head, argv[x] + 1);
            free(name);
            printList( & head);

        }
    }
}

导致错误的问题是您使用的是

strcpy(name, argv[x]);

你应该在哪里使用

strcpy(name, argv[x] + 1);

这导致在尝试删除 ted 时返回由 "error0" 生成的字符串,因为列表包含 +bill+ted


已修复并清理:

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

typedef struct node {
   char        *data;
   struct node *next;
} node;

void printList(struct node *node) {  // Don't need a pointer to a pointer.
    printf("List:");
    for (; node; node = node->next)
        printf(" %s", node->data);
        
    printf("\n");
}

// Returns 0 on success.
// Returns -1 and sets errno on error.
int append(struct node **node_pp, char *name) {  // Better name
   while (*node_pp)
      node_pp = &( (*node_pp)->next );

    struct node *newNode = malloc(sizeof(struct node));
    if (!newNode)
        return -1;

    newNode->data = name;
    newNode->next = NULL;

    *node_pp = newNode;
    return 0;
}

// Returns NULL if not found.
char *removeNode(struct node **node_pp, const char *name) {  // Added `const`
    for (; *node_pp; next_p = &( (*node_pp)->next )) {
        if (strcmp((*node_pp) -> data, name) == 0) {
            struct node * oldNode = *next_p;
            *node_pp = oldNode->next;

            char *data = oldNode->data;
            free(oldNode);
            return data;
        }
    }

    return NULL;  // NULL is a far better value to return on error.
}

int main(int argc, char * argv[]) {
    struct node *head = NULL;
    for (int x = 1; x < argc; x++) {
        if (argv[x][0] == '+') {
            char *name = strdup(argv[x] + 1);  // Simpler
            if (name == NULL) {
                perror("Can't allocate memory");  // Error message is good
                exit(EXIT_FAILURE);
            }

            printf("Appending %s.\n", name);
            if (append(&head, name) < 0) {
                perror("Can't append node to list");
                exit(EXIT_FAILURE);
            }
        } else if (argv[x][0] == '-') {
            const char *name_to_find = argv[x] + 1;
            printf("Removing %s.\n", name_to_find);
            char *name = removeNode(&head, name_to_find);
            if (name) { // Do check if it was found!
               free(name);
            } else {
                printf("%s not found\n", name_to_find);
            }
        }

        printList(head);
        printf("\n");
    }
}

+foo +bar -baz -foo 的输出:

Appending foo.
List: foo

Appending bar.
List: foo bar

Removing baz.
baz not found
List: foo bar

Removing foo.
List: bar