从函数返回一个指针,然后释放指针

Posted

技术标签:

【中文标题】从函数返回一个指针,然后释放指针【英文标题】:Return a pointer from a function, then free the pointer 【发布时间】:2022-01-07 14:15:45 【问题描述】:

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

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);

        
    

【问题讨论】:

removeNode 释放返回值会导致很大的问题,因为返回值有时是"error0"。另外,不用两行代码分配空间并将argv[x]复制到name,只需使用char *name = strdup(argv[x]); 样式指南:点. 和箭头-&gt; 运算符绑定非常紧密,因为它们是postfix operators。它们的周围不应有空格。写current -&gt; data 不是惯用的C 语言,表示编码器是一个tyro(新手)。使用current-&gt;data 【参考方案1】:

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

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

【讨论】:

以上是关于从函数返回一个指针,然后释放指针的主要内容,如果未能解决你的问题,请参考以下文章

16. 指针函数和函数指针

从 C 中的其他函数内部释放指针

分配函数和返回的指针

为啥free函数不在释放内存后,将指针置NULL,野指针有啥用

如何释放C中两个指针指向的内存? [复制]

C 语言结构体 ( 结构体中嵌套一级指针 | 分配内存时先 为结构体分配内存 然后再为指针分配内存 | 释放内存时先释放 指针成员内存 然后再释放结构头内存 )