【问题标题】:Function will only properly work if I've printed the values of the attributes仅当我打印了属性的值时,功能才能正常工作
【发布时间】:2020-04-26 01:52:39
【问题描述】:

我正在尝试为大学创建一个库来处理来自 XML 文件的音乐分区。 我不想详细介绍,但我有一个函数可以创建分区 score,另一个函数可以添加单独的注释 score_add_note

原型如下:

score_t* score(size_t tempo, size_t duration, size_t sig, size_t nbInstr)
void score_add_note(score_t* sc, size_t ins, size_t bar, pitch_t p, size_t start, size_t duration)

我还将 XML 文件转换为我制作的结构,在本例中称为 e

有一次,我这样使用这些函数:

score_t* sc = score(atoi(e->at_head->value), atoi(e->at_head->next->value), atoi(e->at_head->next->next->value), atoi(e->at_head->next->next->next->value));
score_add_note(sc, 0, 0, 60, 0, 6);

属性是 XML 结构的一部分。

这不起作用,score_add_note 函数永远不会停止执行。

但是,如果我事先将属性中的值打印到 score 函数,它可以正常工作:

printf("%d\n", atoi(e->at_head->value));
printf("%d\n", atoi(e->at_head->next->value));
printf("%d\n", atoi(e->at_head->next->next->value));
printf("%d\n", atoi(e->at_head->next->next->next->value));

score_t* sc = score(atoi(e->at_head->value), atoi(e->at_head->next->value), atoi(e->at_head->next->next->value), atoi(e->at_head->next->next->next->value));
score_add_note(sc, 0, 0, 60, 0, 6);

是我犯了一些错误还是这是 C 中的一个错误。如果是这样,有什么办法可以解决吗? 顺便说一句,我使用 gcc 作为我的编译器。

编辑: 如要求,这是score_add_note 函数

void score_add_note(score_t* sc, size_t ins, size_t bar, pitch_t p, size_t start, size_t duration){
    if(sc->system[ins].tab[bar] == NULL){
        sc->system[ins].tab[bar] = (bar_t*) malloc (sizeof(bar_t));
        sc->system[ins].tab[bar]->start = start;
        sc->system[ins].tab[bar]->duration = duration;
        sc->system[ins].tab[bar]->pitch = p;
    }else{
        note_t* note = sc->system[ins].tab[bar];
        while(1){
            if(note->next == NULL){
                note->next = (note_t*) malloc (sizeof(note_t));
                note = note->next;
                break;
            } 
            note = note->next;
        }
        note->start = start;
        note->duration = duration;
        note->pitch = p;
    } 
}

函数有可能陷入无限循环,但两种情况下的参数相同。

这是score 函数:

score_t* score(size_t tempo, size_t duration, size_t sig, size_t nbInstr){
    score_t* sc = (score_t*) malloc (sizeof(score_t));
    sc->tempo = tempo / 60;
    sc->duration = duration;
    sc-> time_sig = sig;
    sc->sys_size = nbInstr;
    sc->system = (staff_t*) malloc (nbInstr * sizeof(staff_t));
    for(int i = 0; i < nbInstr; i++){
        sc->system[i].tab = (bar_t**) malloc (duration * sizeof(bar_t*));
    }
    return sc;
}

这些是我创建的类型:

typedef struct note_s{
    size_t start;
    size_t duration;
    pitch_t pitch;
    struct note_s* next;
}note_t;


typedef note_t bar_t;

typedef struct staff_s{
    bar_t** tab;
}staff_t;


struct score_s{
    size_t tempo;
    size_t duration;
    size_t time_sig;
    size_t sys_size;
    staff_t* system;
};

【问题讨论】:

  • @asbestos_moccasin 这个函数或者周围的代码有问题。由于行为基于看似不相关的更改而有所不同,因此您的代码调用未定义行为的可能性很高(> 99%)。相比之下,出现编译器错误的可能性为
  • 我不想详细说明,没关系,但您必须至少提供解决问题所需的详细信息。如果可能,准备一个非常小的代码示例,其中包含的内容仅足以说明您所看到的问题并使用该示例编辑您的帖子。 (minimal reproducible example)
  • 您不会终止您的列表。在添加节点期间,您永远不会将 NULL 分配给 note-&gt;next;(用于新创建的注释)。可能您的 score() 函数包含相同的错误。但是由于您没有向我们展示强制性的 MCVE,而只是向我们展示了一些不完整的 sn-ps,因此我们无法确定出了什么问题。
  • @darnir 附带说明,请不要为您的类型使用 _t 后缀。它是 C 实现添加新类型的保留后缀 不在 C11 中:7.1.3 Reserved identifiers
  • @darnir 那只是limited to [u]int*_t

标签: c


【解决方案1】:

这段代码

    note_t* note = sc->system[ins].tab[bar];
    while(1){
        if(note->next == NULL){
            note->next = (note_t*) malloc (sizeof(note_t));
            note = note->next;
            break;
        } 
        note = note->next;
    }

在链表上创建新节点时从不将note-&gt;next 设置为NULL。因此,您稍后在访问列表时会调用未定义的行为。

这样会更好:

    note_t* note = sc->system[ins].tab[bar];
    while (1) {
        if (note->next == NULL){
            note->next = malloc(sizeof *note->next);
            note = note->next;
            note->next = NULL;
            break;
        } 
        note = note->next;
    }

【讨论】:

  • 谢谢,但这似乎不是问题。
  • sc-&gt;system[ins].tab[bar] = (bar_t*) malloc (sizeof(bar_t)); 也是这种情况,其中next 既未设置为 null。
  • 我也改正了,但这也不是问题。
  • @asbestos_moccasin 那么您未发布的代码中可能存在问题。如果您使用的是 Linux,请尝试 using Valgrind 查找内存访问问题。
  • @asbestos_moccasin 我已经在我的第一条评论中提到您的score 函数中可能有类似的问题。你也解决了吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-04
  • 1970-01-01
相关资源
最近更新 更多