我在这里啊@ 2024-06-15 10:45 采纳率: 0%
浏览 19

使用LIbcyaml解析netcfg.yaml配置文件是出现段错误

libcyaml库使用问题

network:
  ethernets:
    eth0:
      dhcp4: false
      addresses:
      - 192.168.0.123/24
      #gateway4: 192.168.0.1
      nameservers:
        addresses:
        - 114.114.114.114
        - 8.8.8.8
    eth1:
      dhcp4: false
      addresses:
      - 192.168.137.147/24
      gateway4: 192.168.137.1
      nameservers:
        addresses:
        - 114.114.114.114
        - 8.8.8.8
    enP1p17s0:
      dhcp4: false
      addresses:
      - 192.168.2.123/24
      #gateway4: 192.168.2.1
      nameservers:
        addresses:
        - 114.114.114.114
        - 8.8.8.8
    enP2p33s0:
      dhcp4: false
      addresses:
      - 192.168.3.123/24
      #gateway4: 192.168.3.1
      nameservers:
        addresses:
        - 114.114.114.114
        - 8.8.8.8
    eth2:
      dhcp4: false
      addresses:
      - 192.168.4.123/24
      #gateway4: 192.168.4.1
      nameservers:
        addresses:
        - 114.114.114.114
        - 8.8.8.8
    wlan0:
      dhcp4: true
  version: 2

这个是Linux的Netplan配置文件,我用Libcyaml库对这个文件进行解析和修改,以下是我的代码和结构体,在Ubuntu上运行正常(但是调用cyaml_free的时候会崩溃),移植到开发板上后程序运行直接就会提示段错误(cyaml_load_file函数里),不明白问题出在哪

/*
 * SPDX-License-Identifier: ISC
 *
 * Copyright (C) 2019 Michael Drake <tlsa@netsurf-browser.org>
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "./cyaml.h"

/******************************************************************************
 * C data structure for storing a project plan.
 *
 * This is what we want to load the YAML into.
 ******************************************************************************/

struct nameservers {
    char **addresses;
    unsigned n_addresses;
};

struct wlan0 {
    char *dhcp4;
};

struct ethx {
    char *dhcp4;
    char **addresses;
    unsigned n_addresses;
    struct nameservers *nameserver;
};

struct ethx_gateway {
    char *dhcp4;
    char **addresses;
    unsigned n_addresses;
    char *gateway4;
    struct nameservers *nameserver;
};


struct ethernets {
    struct ethx *eth0;
    struct ethx_gateway *eth1;
    struct ethx *enP1p17s0;
    struct ethx *enP2p33s0;
    struct ethx *eth2;
    struct wlan0 *wlan0;
};

struct network {
    struct ethernets *ethernet;
    char *version;
};

struct netplan {
    struct network *net;
};


/******************************************************************************
 * CYAML schema to tell libcyaml about both expected YAML and data structure.
 *
 * (Our CYAML schema is just a bunch of static const data.)
 ******************************************************************************/
static const cyaml_schema_value_t string_ptr_schema = {
    CYAML_VALUE_STRING(CYAML_FLAG_POINTER, char, 0, CYAML_UNLIMITED),
};

static const cyaml_schema_field_t address_fields_schema[] = {
    CYAML_FIELD_SEQUENCE_COUNT(
            "addresses", CYAML_FLAG_POINTER,
            struct nameservers, addresses, n_addresses,
            &string_ptr_schema, 0, CYAML_UNLIMITED),
};

static const cyaml_schema_field_t wlan0_fields_schema[] = {
    CYAML_FIELD_STRING_PTR(
            "dhcp4", CYAML_FLAG_DEFAULT,
            struct wlan0, dhcp4, 0, CYAML_UNLIMITED),
};

static const cyaml_schema_field_t ethx_fields_schema[] = {
    CYAML_FIELD_STRING_PTR(
            "dhcp4", CYAML_FLAG_DEFAULT,
            struct ethx, dhcp4, 0, CYAML_UNLIMITED),

    CYAML_FIELD_SEQUENCE_COUNT(
            "addresses", CYAML_FLAG_POINTER,
            struct ethx, addresses, n_addresses,
            &string_ptr_schema, 0, CYAML_UNLIMITED),

    CYAML_FIELD_MAPPING_PTR(
            "nameservers", CYAML_FLAG_POINTER,
            struct ethx, nameserver, address_fields_schema),

    CYAML_FIELD_END
};

static const cyaml_schema_field_t ethx_gateway_fields_schema[] = {
    CYAML_FIELD_STRING_PTR(
            "dhcp4", CYAML_FLAG_DEFAULT,
            struct ethx_gateway, dhcp4, 0, CYAML_UNLIMITED),

    CYAML_FIELD_SEQUENCE_COUNT(
            "addresses", CYAML_FLAG_POINTER,
            struct ethx_gateway, addresses, n_addresses,
            &string_ptr_schema, 0, CYAML_UNLIMITED),

    CYAML_FIELD_STRING_PTR(
            "gateway4", CYAML_FLAG_DEFAULT,
            struct ethx_gateway, gateway4, 0, CYAML_UNLIMITED),

    CYAML_FIELD_MAPPING_PTR(
            "nameservers", CYAML_FLAG_POINTER,
            struct ethx_gateway, nameserver, address_fields_schema),

    CYAML_FIELD_END
};

static const cyaml_schema_field_t ethernet_fields_schema[] = {
    CYAML_FIELD_MAPPING_PTR(
            "eth0", CYAML_FLAG_POINTER,
            struct ethernets, eth0, ethx_fields_schema),

    CYAML_FIELD_MAPPING_PTR(
            "eth1", CYAML_FLAG_POINTER,
            struct ethernets, eth1, ethx_gateway_fields_schema),

    CYAML_FIELD_MAPPING_PTR(
            "enP1p17s0", CYAML_FLAG_POINTER,
            struct ethernets, enP1p17s0, ethx_fields_schema),

    CYAML_FIELD_MAPPING_PTR(
            "enP2p33s0", CYAML_FLAG_POINTER,
            struct ethernets, enP2p33s0, ethx_fields_schema),    

    CYAML_FIELD_MAPPING_PTR(
            "eth2", CYAML_FLAG_POINTER,
            struct ethernets, eth2, ethx_fields_schema),    

    CYAML_FIELD_MAPPING_PTR(
            "wlan0", CYAML_FLAG_POINTER,
            struct ethernets, wlan0, wlan0_fields_schema),    

    CYAML_FIELD_END    
};


static const cyaml_schema_field_t net_fields_schema[] = {
    CYAML_FIELD_MAPPING_PTR(
            "ethernets", CYAML_FLAG_POINTER,
            struct network, ethernet, ethernet_fields_schema),

    CYAML_FIELD_STRING_PTR(
            "version", CYAML_FLAG_DEFAULT,
            struct network, version, 0, CYAML_UNLIMITED),

    CYAML_FIELD_END
};

static const cyaml_schema_field_t network_fields_schema[] = {
    CYAML_FIELD_MAPPING_PTR(
            "network", CYAML_FLAG_POINTER,
            struct netplan, net, net_fields_schema),
};

static const cyaml_schema_value_t netplan_schema = {
    CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
            struct netplan, network_fields_schema),
};

static const cyaml_config_t config = {
    .log_fn = cyaml_log,            /* Use the default logging function. */
    .mem_fn = cyaml_mem,            /* Use the default memory allocator. */
    .log_level = CYAML_LOG_WARNING, /* Logging errors and warnings only. */
};
#define NETPLAN_PATH "/etc/netplan/netplan.yaml"



/* Main entry point from OS. */
int main(int argc, char *argv[])
{
    cyaml_err_t err;
    struct netplan *g_netplan;

    printf("2221\n");
        /* Load input file. */
    err = cyaml_load_file("netplan.yaml", &config,
            &netplan_schema, (void **) &g_netplan, NULL);
    if (err != CYAML_OK) {
        printf("ERROR11: %s\n", cyaml_strerror(err));
        return EXIT_FAILURE;
    }

    printf("111\n");
    // /* Use the data. */
    printf("%s\n", g_netplan->net->ethernet->eth0->dhcp4);
    printf("%s\n", g_netplan->net->ethernet->eth0->addresses[0]);
    printf("%s\n", g_netplan->net->ethernet->eth0->nameserver->addresses[0]);
    printf("%s\n", g_netplan->net->ethernet->eth0->nameserver->addresses[1]);

    printf("%s\n", g_netplan->net->ethernet->eth1->dhcp4);
    printf("%s\n", g_netplan->net->ethernet->eth1->addresses[0]);
    printf("%s\n", g_netplan->net->ethernet->eth1->gateway4);
    printf("%s\n", g_netplan->net->ethernet->eth1->nameserver->addresses[0]);
    printf("%s\n", g_netplan->net->ethernet->eth1->nameserver->addresses[1]);

    printf("%s\n", g_netplan->net->ethernet->enP1p17s0->dhcp4);
    printf("%s\n", g_netplan->net->ethernet->enP1p17s0->addresses[0]);
    printf("%s\n", g_netplan->net->ethernet->enP1p17s0->nameserver->addresses[0]);
    printf("%s\n", g_netplan->net->ethernet->enP1p17s0->nameserver->addresses[1]);

    printf("%s\n", g_netplan->net->ethernet->enP2p33s0->dhcp4);
    printf("%s\n", g_netplan->net->ethernet->enP2p33s0->addresses[0]);
    printf("%s\n", g_netplan->net->ethernet->enP2p33s0->nameserver->addresses[0]);
    printf("%s\n", g_netplan->net->ethernet->enP2p33s0->nameserver->addresses[1]);

    printf("%s\n", g_netplan->net->ethernet->eth2->dhcp4);
    printf("%s\n", g_netplan->net->ethernet->eth2->addresses[0]);
    printf("%s\n", g_netplan->net->ethernet->eth2->nameserver->addresses[0]);
    printf("%s\n", g_netplan->net->ethernet->eth2->nameserver->addresses[1]);

    printf("%s\n", g_netplan->net->version);

    memcpy(g_netplan->net->ethernet->eth0->dhcp4, "true", sizeof("true"));

    /* Save data to new YAML file. */
    err = cyaml_save_file("./test.yaml", &config,
            &netplan_schema, g_netplan, 0);
    if (err != CYAML_OK) {
        fprintf(stderr, "ERROR: %s\n", cyaml_strerror(err));
        cyaml_free(&config, &netplan_schema, g_netplan, 0);
        return EXIT_FAILURE;
    }
    /* Free the data */
    cyaml_free(&config, &netplan_schema, &g_netplan, 0);
    return EXIT_SUCCESS;
}


  • 写回答

2条回答 默认 最新

  • 阿里嘎多学长 2024-06-15 11:34
    关注

    以下内容由CHATGPT及阿里嘎多学长共同生成、有用望采纳:


    在处理C语言和libcyaml库解析YAML文件时出现的段错误,通常有以下几个可能的原因:

    1. 内存分配问题:在嵌入式系统或开发板上,可能存在内存限制或碎片化,导致动态内存分配失败。
    2. 指针错误:可能存在野指针或越界访问,特别是在结构体数组或指针操作中。
    3. 环境差异:Ubuntu和开发板的编译环境可能不同,包括编译器、库版本、系统调用等。
    4. libcyaml库的兼容性:可能存在库的版本不兼容或者某些功能在特定平台上未实现或有bug。
    5. YAML文件格式问题:尽管你的代码在Ubuntu上运行正常,但YAML文件格式的某些细节可能在不同平台上解析有差异。

    针对你的问题,以下是一些解决步骤和建议:

    1. 检查内存分配

    • 确保开发板上有足够的内存可供程序使用。
    • 使用工具如valgrind检查内存泄漏和越界访问。

    2. 检查环境差异

    • 确保开发板上的编译器、libcyaml库和其他依赖库与Ubuntu上的版本一致或兼容。

    3. 调试段错误

    • 使用gdb等调试工具运行程序,查看段错误发生时的调用栈和变量状态。
    • cyaml_load_file函数前后添加日志输出,以确定错误发生的具体位置。

    4. 检查代码逻辑

    • 确认你的数据结构是否正确地映射了YAML文件的结构。
    • 检查是否正确处理了YAML文件中的注释和空值。

    5. 处理cyaml_free崩溃问题

    • 确保在调用cyaml_free之前,所有动态分配的内存都已经被正确地初始化和使用。
    • 检查cyaml_free的调用参数是否正确,确保传递了正确的配置和数据结构。

    6. 参考资料

    • libcyaml的官方文档和GitHub仓库是解决问题的好地方:libcyaml GitHub
    • 有关YAML解析和C语言内存管理的教程和论坛讨论。

    7. 代码实现建议

    • 考虑使用更现代的YAML解析库,如libyaml,它可能提供更好的错误处理和更广泛的平台支持。
    • 在处理YAML文件时,使用异常处理或错误检查机制来确保程序的健壮性。

    最后,如果你需要进一步的帮助,可以提供更详细的错误信息或日志,以便更准确地定位问题。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 6月15日