访问结构体内指针数组的指针导致出现分段错误

问题描述:

我在尝试访问cart_t中的**addr变量的item_t指针的成员时遇到困难。的cart_t的定义如下:访问结构体内指针数组的指针导致出现分段错误

typedef struct cart_struct { 
    item_t **addr; 
    int ptr; 
    float total; 
} cart_t; 

我已经初始化,并使用下面的代码添加项目到**addr

​​

正如你可以在上面的代码中看到,调试printf实际工作。但是,当我稍后再尝试去做就cart.addr[n],它会导致分段错误:

// cart_t canteen_cart 
// item_t *item_current 
... 
if (cart_append_item(&canteen_cart, item_current) == NULL) { 
    // error. clean up 
} 
... 
printf("[TEST] price %f, quantity %d, total %f\n", canteen_cart.addr[canteen_cart.ptr-1]->price, canteen_cart.addr[canteen_cart.ptr-1]->quantity, canteen_cart.addr[canteen_cart.ptr-1]->price * canteen_cart.addr[canteen_cart.ptr-1]->quantity); // segmentation fault 
... 

谢谢!的int main()


摘录:

int main() { 
    cart_t canteen_cart; 
    canteen_cart.addr = NULL; 
    canteen_cart.ptr = 0; 
    canteen_cart.total = 0.0f; 

    item_t *item_current = NULL; 

    ... 
    a hundred of lines later of user input thingy 
    ... 

    if (state == STATE_CHECKOUT) { 
     printf("[TEST] %d\n", canteen_cart.addr == NULL); // returns 0 
     printf("[TEST] %d\n", canteen_cart.ptr > 0); // returns 1, there are some items in the array 
     printf("price %f, quantity %d, total %f\n", canteen_cart.addr[canteen_cart.ptr-1]->price, canteen_cart.addr[canteen_cart.ptr-1]->quantity, canteen_cart.addr[canteen_cart.ptr-1]->price * canteen_cart.addr[canteen_cart.ptr-1]->quantity); 
    print_view_checkout(&canteen_cart); // SEGMENTATION FAULT HERE 
    } 

    cart_free_items(&canteen_cart); // free cart and all the members within it. 

    return 0; 

} 
+0

看来你可能需要了解[*'realloc' *](HTTP ://en.cppreference.com/w/c/memory/realloc)。 –

+1

至于你的问题,变量'canteen_cart'何时定义?它是如何初始化的?您可以创建一个[最小,完整和可验证示例](http://*.com/help/mcve)并向我们展示? –

+0

我正在考虑使用'realloc',但是我继续用'malloc'''ree'对来代替... –

现在,当我们可以看到如何初始化canteen_cart,采取从cart_append_item功能这线:

new[i+1] = item; 

在很首先调用cart_append_item函数,值为cart->ptr(i t的名字确实不好)是0。这意味着循环将不会迭代,并且i的值将为零。这意味着您实际上正在做new[1] = item,其中new仅具有索引0的单个元素的空间。这写越界当然导致undefined behavior,使您的整个程序不健康和无效。并容易崩溃。

对于连续拨打cart_append_item的每个连续呼叫,您仍然会写出越界。

简单的解决方案?改为使用new[cart->ptr] = item


那么对于我的realloc评论,你可以酌情利用realloc使功能,因此更短和更简单:

cart_t *cart_append_item(cart_t *cart, item_t *item) { 
    if (cart == NULL || item == NULL) 
     return NULL; 

    item_t **new_items = realloc(cart->addr, sizeof *cart->addr * cart->ptr + 1); 
    if (new_items == NULL) { 
     return NULL; 
    } 

    cart->addr = new_items; 

    // Add the new item 
    cart->addr[cart->ptr++] = item; 

    cart->total += item->price * item->quantity; 

    return cart; 
}