为什么将此C代码段标记为错误?

时间:2019-06-19 16:41:55

标签: c

我是c的新手。我在C中遇到了这段代码,它被标记为错误代码。不知道为什么它不好,还有改进的建议吗?

原始代码来自此链接:

https://pastebin.com/r2rTN6Zf

typedef struct {
    bool is_married;
    uint8_t age;
    uint8_t num_children;
} personal_info;

int lookup_personal_info(char *first_name, void *last_name, uint8_t (*sin)[9], const struct **info_out)
{
    // Sanity check.
    if (!first_name || !last_name || !sin)
        return false;

    char *initials[3] = { first_name[0], last_name[1] };

    // Allocate space for the output.
    personal_info *data = malloc(sizeof(struct personal_info));
    if (!data)
        goto fail;

    // Look up the personal info by initials.
    bool is_ok = database_lookup(initials, &data);
    if (is_ok)
        goto fail;

    // Assign the found data to the output parameter.
    *info_out = (personal_info *) data;

    // Success!
    return true;

fail:
    data = NULL;
    free(data);

    return true;
}

3 个答案:

答案 0 :(得分:2)

在调用NULL之前设置指向free的指针会使对free的调用变为良性(即不执行任何操作)。

如果您的IDE中有一个静态分析工具可以检查并且可能是不正确的代码,那么它被它选中就不会感到惊讶。

安全地调用free的惯用方式是将free -d指针设置为NULL,在调用之后 而不是之前。

答案 1 :(得分:2)

任何体面的linter都会用此代码标记许多问题。这是Atom editor提供的内容,加上我的目光。

int lookup_personal_info(char *first_name, void *last_name, uint8_t (*sin)[9], const struct **info_out)
  • last_name被声明为void *,但用作char *
  • const struct **info_out声明了一个匿名结构。应该是personal_info **info_out
  • 该函数返回bool而不是int
  • sin仅用于检查它是否传入。
    if (!first_name || !last_name || !sin)
        return false;
  • 传入空指针可能是调用者的一个错误。这无声地忽略了该错误,使它很难被发现。它应该引发一个错误。
  • 它忘记检查info_out
    char *initials[3] = { first_name[0], last_name[1] };
  • 这是用char初始化的字符指针数组。应该是char initials[3]
  • 它不是以null终止的。也许不是必须的,但我不会冒险。
  • last_name被声明为void *,但仍被用作char *
  • 它使用first_name的第一个字符作为首字母,这是有道理的,但是为什么在last_name中使用第二个……东西呢?
    personal_info *data = malloc(sizeof(struct personal_info));

struct personal_info不是类型,类型是personal_info

    *info_out = (personal_info *) data;

info_out被错误地声明为匿名结构。它应该是personal_info **info_out。这样就不需要类型转换了。

    bool is_ok = database_lookup(initials, &data);
    if (is_ok)
        goto fail;

检查是向后的。

使用goto可以确保正确清除错误。该示例中可能包含红色鲱鱼。

fail:
    data = NULL;
    free(data);

    return true;
    在清空free泄漏的内存之后,调用
  • data
  • 无需将data设置为NULL,因为它对于即将退出的函数是本地的。
  • 失败和成功均返回true

答案 2 :(得分:0)

这对我来说没有多大意义。为什么释放NULL指针...

fail:
    data = NULL;
    free(data);