首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >带有自定义类型的可变C函数

带有自定义类型的可变C函数
EN

Stack Overflow用户
提问于 2018-05-15 03:08:31
回答 1查看 236关注 0票数 1

我想实现一个用于获取自定义类型参数的变量函数,而不是像GNU的示例中那样:

https://www.gnu.org/software/libc/manual/html_node/Variadic-Example.html#Variadic-Example

在我的逻辑中,我处理的是节点,由下面的tpye定义:

代码语言:javascript
复制
typedef struct node_t {
    char *key;
    node_type_t type;
    apr_array_header_t *arr_strings;
    apr_array_header_t *arr_numbers;
} node_t;

这样的节点根据以这种方式定义的特定类型(字符串、数字)将信息存储在不同的APR数组中:

代码语言:javascript
复制
typedef enum node_type_t {
    node_type_string,
    node_type_number,
} node_type_t;

该函数如下所示:

代码语言:javascript
复制
int add_node(apr_pool_t *p_pool, node_t *p_target_node, ...) {
    int rv = 0;
    va_list lmnts;
    va_start(lmnts, p_target_node);
    node_t *n = va_arg(lmnts, node_t *);
    apr_array_header_t *tbl;
    do {
        switch(n->type) {
            case node_type_string:
                tbl = p_target_node->arr_strings;
                break;
            case node_type_number:
                tbl = p_target_node->arr_numbers;
                break;
            default:
                break;
        }
        printf("\t\t%d - %s\n", rv, n->key);
        *(const node_t**)apr_array_push(tbl) = n;
        rv++;
    } while (n && ((n = va_arg(lmnts, node_t *)) != NULL) &&   apr_strnatcmp(n->key, p_target_node->key) != 0);
    va_end(lmnts);
    return rv;
}

它适用于two node_t参数,但对于更多的参数,我得到了分段错误。

这是完整的代码:

代码语言:javascript
复制
#include <stdarg.h>
#include <stdio.h>

#include <apr_general.h>
#include <apr_hash.h>
#include <apr_pools.h>
#include <apr_strings.h>
#include <apr_tables.h>

typedef enum node_type_t {
    node_type_string,
    node_type_number,
} node_type_t;

typedef struct node_t {
    char *key;
    node_type_t type;
    apr_array_header_t *arr_strings;
    apr_array_header_t *arr_numbers;
} node_t;

node_t *create_node(apr_pool_t *p_pool, char *p_key, node_type_t p_type) {
    node_t *NODE = apr_palloc(p_pool, sizeof(node_t));
    NODE->key = p_key;
    NODE->type = p_type;
    NODE->arr_strings = apr_array_make(p_pool, 0, sizeof(node_t*));
    NODE->arr_numbers = apr_array_make(p_pool, 0, sizeof(node_t*));
    return NODE;
}

int add_node(apr_pool_t *p_pool, node_t *p_target_node, ...) {
    int rv = 0;
    va_list lmnts;
    va_start(lmnts, p_target_node);
    node_t *n = va_arg(lmnts, node_t *);
    apr_array_header_t *tbl;
    do {
        switch(n->type) {
            case node_type_string:
                tbl = p_target_node->arr_strings;
                break;
            case node_type_number:
                tbl = p_target_node->arr_numbers;
                break;
            default:
                break;
        }
        printf("\t\t%d - %s\n", rv, n->key);
        *(const node_t**)apr_array_push(tbl) = n;
        rv++;
    } while (n && ((n = va_arg(lmnts, node_t *)) != NULL) && apr_strnatcmp(n->key, p_target_node->key) != 0);
    va_end(lmnts);
    return rv;
}

int add_node(apr_pool_t *p_pool, node_t *p_target_node, ...) {
    int rv = 0;
    va_list lmnts;
    va_start(lmnts, p_target_node);
    node_t *n = va_arg(lmnts, node_t *);
    while((n = va_arg(lmnts, node_t *)) != NULL && apr_strnatcmp(n->key, p_target_node->key) != 0) {
        printf("\t\t%d - %s\n", rv, n->key);
        *(const node_t**)apr_array_push(p_target_node->arr_strings) = n;
        rv++;
    }
    va_end(lmnts);
    return rv;
}

int main(int argc, const char *argv[]) {
    apr_status_t rv;
    apr_pool_t *mp;

    rv = apr_initialize();
    if (rv != APR_SUCCESS) {
        return -1;
    }
    apr_pool_create(&mp, NULL);

    node_t *ROOT_NODE = create_node(mp, "THE_ROOT", node_type_string);
    printf("\tROOT_NODE { key: '%s', type: %d, [%d, %d]}\n", 
        ROOT_NODE->key, ROOT_NODE->type,
        ROOT_NODE->arr_strings->nelts, ROOT_NODE->arr_numbers->nelts);

    node_t *NODE_A = create_node(mp, "A", node_type_string);
    printf("\tNODE_A { key: '%s', type: %d, [%d, %d]}\n", 
        NODE_A->key, NODE_A->type,
        NODE_A->arr_strings->nelts, NODE_A->arr_numbers->nelts);

    node_t *NODE_B = create_node(mp, "B", node_type_number);
    printf("\tNODE_B { key: '%s', type: %d, [%d, %d]}\n", 
        NODE_B->key, NODE_B->type,
        NODE_B->arr_strings->nelts, NODE_B->arr_numbers->nelts);

    node_t *NODE_C = create_node(mp, "C", node_type_string);
    printf("\tNODE_C { key: '%s', type: %d, [%d, %d]}\n", 
        NODE_C->key, NODE_C->type,
        NODE_C->arr_strings->nelts, NODE_C->arr_numbers->nelts);

    add_node(mp, ROOT_NODE, NODE_A, NODE_B, NODE_C);

    printf("\tn = %d, n = %d\n", ROOT_NODE->arr_strings->nelts, ROOT_NODE->arr_numbers->nelts);

    apr_pool_destroy(mp);
    apr_terminate();
    return 0;
}
EN

回答 1

Stack Overflow用户

发布于 2018-05-28 09:16:43

我看到的问题是,您的add_node()似乎会检查NULL参数以确定参数列表是否已完成,但您在调用它时从不传递NULL参数,因此add_node将在遍历您传递的所有参数后继续读取不存在的“参数”,访问内存中它不应该访问的位置,并导致各种糟糕的问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50337390

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档