【问题标题】:runtime error: member access within null pointer of type 'struct ListNode' [solution.c]运行时错误:“struct ListNode”类型的空指针内的成员访问 [solution.c]
【发布时间】:2022-01-15 10:02:47
【问题描述】:

我正在尝试使用非递归解决方案解决 leetcode 上的合并 k 排序列表问题。当我运行代码时,它会给出如下所述的错误。你能帮我解决问题吗? 错误在列表[min_idx] = lists[min_idx]->next;

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* mergeKLists(struct ListNode** lists, int listsSize){
    
    struct ListNode *result;
    result = (struct ListNode *)malloc(sizeof(struct ListNode));
    result = NULL;
    struct ListNode *p;
    if (!listsSize){
        return result;
    }
    
    int min = INT_MAX;
    int min_idx = 0;
    int cnt=0;
    while (lists){
        for ( int i = 0 ; i<listsSize ; i++){
            if (lists[i]){
                cnt=0;
                if (lists[i]->val < min){
                    min = lists[i]->val;
                    min_idx = i;
                }
            }
            else {
                cnt++;
            }
        }
        if (cnt==listsSize){
            break;
        }
        
        struct ListNode *temp;
        temp = (struct ListNode *)malloc(sizeof(struct ListNode));
        temp->val = min;
        temp->next = NULL;
        if (result == NULL){
            result = temp;
            p = temp;
        }
        else {
            p->next = temp;
            p = p->next;
        }
        lists[min_idx] = lists[min_idx]->next;
    }
    return result;
}

错误:

Line 52: Char 40: runtime error: member access within null pointer of type 'struct ListNode' [solution.c]. 

【问题讨论】:

  • 您应该使用调试器并找到程序崩溃的位置。
  • 第 52 行在哪里?
  • 在取消引用之前,您不会检查temp 是否拥有有效地址。
  • result = (struct ListNode *)... 您对result 的第一次分配是无用的,并且在您之后立即将其设置为NULL 时也会导致内存泄漏。同样在 C 中,您不需要区分 malloc 的结果
  • 如果结果创建后没有设置为null,leetcode编译器显示运行时错误为SEGV未知地址...

标签: c merge linked-list singly-linked-list function-definition


【解决方案1】:

对于初学者来说,即使是前两行也会产生内存泄漏

result = (struct ListNode *)malloc(sizeof(struct ListNode));
result = NULL;

这个while循环

while (lists){

可以是一个无限循环,因为按照惯例,这个指针不能等于 NULL,因为它是指向数组第一个元素的指针。如果用户专门将空指针传递给与功能要求相矛盾的函数,则可以等于NULL。

这段代码sn-p

    for ( int i = 0 ; i<listsSize ; i++){
        if (lists[i]){
            cnt=0;
            if (lists[i]->val < min){
                min = lists[i]->val;
                min_idx = i;
            }
        }
        else {
            cnt++;
        }
    }
    if (cnt==listsSize){
        break;
    }

不清楚,本质上没有意义。

直截了当的方法可以看一下例如下面的方式

struct ListNode * mergeKLists( struct ListNode **lists, size_t listsSize )
{
    struct ListNode *head = NULL;
    struct ListNode **current = &head;

    int empty = 1;

    do
    {
        size_t i = 0;

        while ( i < listsSize && lists[i] == NULL ) i++;

        empty = i == listsSize;

        if ( !empty )
        {
            size_t min = i;
            
            while ( ++i != listsSize )
            {
                if ( lists[i] != NULL && lists[i]->val < lists[min]->val )
                {
                    min = i;
                }
            }

            *current = lists[min];
            lists[min] = lists[min]->next;
            ( *current )->next = NULL;
            current = &( *current )->next;              
        }
    } while ( !empty );

    return head;
}

【讨论】:

    【解决方案2】:
    • 成对组合
    • 分而治之
    • (原来的数组会被覆盖,结果会在lists[0]

    #include <stddef.h>
    
    struct ListNode {
            struct ListNode *next;
            int val;
            };
    
    
    struct ListNode *mergeTwolists(struct ListNode *one, struct ListNode *two)
    {
    struct ListNode *result, **pp;
    
    if (!one) return two;
    if (!two) return one;
    
    result = NULL;
    for (pp = &result; one && two; pp = &(*pp)->next) {
            if (one->val <= two->val) { *pp = one; one = one->next; }
            else { *pp = two; two = two->next; }
            }
    *pp = (one) ? one : two;
    return result;
    }
    
    struct ListNode *mergeKLists(struct ListNode **lists, unsigned nlist)
    {
    unsigned src,dst;
    
    for(    ; nlist > 1;    ) {                     // while there are pairs
            for (src=dst=0; src < nlist ; src+=2) { // combine pairwise
                    if (src+1 >= nlist) lists[dst++] = lists[src];
                    else lists[dst++] = mergeTwolists(lists[src], lists[src+1]);
                    }
            nlist = dst;    // recurse
            }
    return lists[0];
    }
    

    【讨论】:

      猜你喜欢
      • 2017-11-27
      • 2021-05-02
      • 2023-03-15
      • 2022-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多