【问题标题】:divide by zero in simclist library在 simclist 库中除以零
【发布时间】:2015-01-17 06:47:00
【问题描述】:

在 simclist 链接列表库中,我遇到了在函数 list_findpos() 中除以零的问题。通常我对修改一个广泛使用的 3rd 方库犹豫不决,并且它必须有充分的理由这样做(我没有排除该库使用不正确)。函数定义为:

/* set tmp to point to element at index posstart in l */
static inline struct list_entry_s *list_findpos(const list_t *restrict l, int posstart) {
    struct list_entry_s *ptr;
    float x;
    int i;

    /* accept 1 slot overflow for fetching head and tail sentinels */
    if (posstart < -1 || posstart > (int)l->numels) return NULL;

    x = (float)(posstart+1) / l->numels;
    if (x <= 0.25) {
        /* first quarter: get to posstart from head */
        for (i = -1, ptr = l->head_sentinel; i < posstart; ptr = ptr->next, i++);
    } else if (x < 0.5) {
        /* second quarter: get to posstart from mid */
        for (i = (l->numels-1)/2, ptr = l->mid; i > posstart; ptr = ptr->prev, i--);
    } else if (x <= 0.75) {
        /* third quarter: get to posstart from mid */
        for (i = (l->numels-1)/2, ptr = l->mid; i < posstart; ptr = ptr->next, i++);
    } else {
        /* fourth quarter: get to posstart from tail */
    for (i = l->numels, ptr = l->tail_sentinel; i > posstart; ptr = ptr->prev, i--);
    }

    return ptr;
}

如果l-&gt;numels0,那么第9 行的表达式就有问题。否则代码运行正常(没有泄漏或段错误),但英特尔检查员说这一行发生除以零。建议的更改是:

/* set tmp to point to element at index posstart in l */
static inline struct list_entry_s *list_findpos(const list_t *restrict l, int posstart) {
    struct list_entry_s *ptr;
    float x;
    int i;

    /* accept 1 slot overflow for fetching head and tail sentinels */
    if (posstart < -1 || posstart > (int)l->numels) return NULL;

    if (l->numels == 0){ //avoid division-by-zero on first element
       ptr = l->head_sentinel;
    }
    else{
       x = (float)(posstart + 1) / l->numels;
       if (x <= 0.25) {
          /* first quarter: get to posstart from head */
          for (i = -1, ptr = l->head_sentinel; i < posstart; ptr = ptr->next, i++);
       }
       else if (x < 0.5) {
          /* second quarter: get to posstart from mid */
          for (i = (l->numels - 1) / 2, ptr = l->mid; i > posstart; ptr = ptr->prev, i--);
       }
       else if (x <= 0.75) {
          /* third quarter: get to posstart from mid */
          for (i = (l->numels - 1) / 2, ptr = l->mid; i < posstart; ptr = ptr->next, i++);
       }
       else {
          /* fourth quarter: get to posstart from tail */
          for (i = l->numels, ptr = l->tail_sentinel; i > posstart; ptr = ptr->prev, i--);
       }
    }
    return ptr;
}

想知道是否有人可以对此有使用 simclist 的经验发表评论?


编辑

list_findpos 不是 API 函数;相反,它是一个内部函数。导致问题的调用顺序是:

/* ... */
list_init(...) 
list_attributes_copy(...)
list_append(...) /* <---- list_findpos() is called here, divide by zero */

【问题讨论】:

  • 在我看来numels 是列表中元素的数量,对吗?空列表是许多代码中常见的特殊情况……只需在函数的第一行检查即可。如果列表是空的,您可能根本不想对它做任何事情,所以请预先处理好这个案例。我也不确定所有浮点的内容是关于什么的,但我会把它留给你。
  • 没错——numels 是声明为unsigned int numels的元素个数
  • 调整返回 NULL 的行上的函数,同时检查 numels 是否为 0 作为返回 NULL 的另一个原因

标签: c divide-by-zero


【解决方案1】:

此函数不是库 API 的一部分;这完全是内部的。为了修复它,库的作者/维护者需要知道的是您执行的导致它失败的 API 调用序列。

【讨论】:

  • 这实际上发生在随库分发的示例 2 (ex2.c) 中的调用序列中。即调用顺序为:list_init()list_attributes_copy()list_append()。调用list_append()时报此问题。
  • 对我来说似乎很糟糕。与作者交谈,或寻找更好的图书馆。
猜你喜欢
  • 2016-07-13
  • 2012-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-15
  • 2019-03-17
  • 1970-01-01
相关资源
最近更新 更多