malloc () và realloc () của cấu trúc

Sep 30 2020

Chúng ta có thể cấp phát động bộ nhớ cho các cấu trúc không? Đây có phải là một thủ tục chính xác để tiếp cận một cấu trúc được cấp phát động không? Xin vui lòng cho tôi biết làm thế nào để malloc()và realloc()một cấu trúc.

newnode thuộc loại struct List * nhưng khi bắt đầu lập chỉ mục nó sẽ chuyển thành struct List. Làm thế nào để chuyển đổi này có thể? Hàm insert của tôi chỉ chấp nhận (struct List *) Tôi có nhầm chỗ nào không?

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

struct List {
    char val[20];
};

void insert(struct List *);

int main(void) {
    int i = 0;
    int size = 1;
    struct List *newnode = (struct List *)malloc(size * sizeof(struct List));
    for (i = 0; i < 5; i++) {
        if (size <= i) {
            size = size + size;
            newnode = (struct List *)realloc(newnode, size * sizeof(struct List));
        }
        scanf("%s", newnode[i].val);
        insert(newnode[i]);
    }
    for (i = 0; i < 5; i++) {
        printf("%s\n", newnode[i].val);
    }
    return 0;
}

void insert(struct List *node) {
    printf("%s\n", node->val);
}

Trả lời

1 chqrlie Sep 30 2020 at 00:34

Mã hoạt động ngoại trừ 3 vấn đề:

  • Bạn không kiểm tra lỗi cấp phát bộ nhớ. Cả hai malloc()và realloc()sẽ trả về NULLnếu không thể cấp phát bộ nhớ: bạn sẽ nhận được hành vi không xác định khi tham chiếu newnodenếu điều này xảy ra.

  • để xử lý trường hợp realloc()thất bại một cách khéo léo, bạn nên lưu trữ con trỏ được phân bổ lại vào một biến khác để bạn vẫn có thể truy cập vào mảng trước đó chưa được phân bổ và giải phóng nó.

  • scanf("%s", newnode[i].val); là một lỗ hổng bảo mật: bạn nên giới hạn số byte có thể được lưu trữ cho mảng đích với

    scanf("%19s", newnode[i].val);
    
  • bạn không kiểm tra giá trị trả về của scanf()để phát hiện đầu vào không hợp lệ hoặc bị thiếu.

  • insert()không chèn bất cứ thứ gì.

Đây là phiên bản đã sửa đổi với khả năng xử lý lỗi và tên ít gây nhầm lẫn hơn:

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

struct Item {
    char val[20];
};

//void insert(struct Item *);

int main(void) {
    int i, j;
    int size = 0;
    struct Item *array = NULL;
    for (i = 0; i < 5; i++) {
        if (i >= size) {
            int newsize = size ? 1 : size + size;
            struct Item *newarray = realloc(array, sizeof(*array) * size);
            if (newarray == NULL) {
                perror("cannot reallocate the array");
                break;
            }
            size = newsize;
            array = newarray;
        }
        if (scanf("%19s", array[i].val) != 1) {
            fprintf(stderr, "missing input\n");
            break;
        }
        //insert(array[i]);
    }
    for (j = 0; j < i; i++) {
        printf("%s\n", array[i].val);
    }
    free(array);
    return 0;
}