calloc() 的错误实现引入了除零以及如何通过测试检测它?

问题描述 投票:0回答:1

我有一个作业,其中我必须编写自己的 calloc 函数(以及一些其他 Libc 函数),唯一允许的内置函数是

malloc()
free()

对于上下文:我的作业评分是完全自动化的,一些测试是针对我在服务器上的代码运行的,如果代码通过了所有测试或没有通过,我会得到“通过”或“失败”。
所以我想要表达的是我知道我的代码没有通过要求,但我不知道确切的原因,这只是一个猜测。

这是有问题的代码:

#include <stdlib.h>
#include "libft.h"    // this is where ft_bzero is declared

void    *ft_calloc(size_t nmemb, size_t size)
{
    void    *ptr;

    if (nmemb > (size_t)-1 / size && size)
        return (NULL);
    ptr = malloc(nmemb * size);
    if (!ptr)
        return (NULL);
    ft_bzero(ptr, nmemb * size);
    return (ptr);
}

我认为我的错误是我错误地定位了条件参数,它应该是这样的:

if (size && nmemb > (size_t)-1 / size)

这样我们在除法之前检查大小是否为零,这会引入未定义的行为。

如果这确实是错误,并且我的代码中没有其他麻烦,那么您如何通过运行一些测试来检测到这一点?

我尝试过调用大小为 0 的函数,它没有使我的程序崩溃,我也尝试过使用

clang -fsanitize=integer-divide-by-zero
进行编译,并且在运行时没有产生任何错误。

我知道根据定义,未定义的行为是未定义的,因此没有真正的方法来检测它,但似乎后端服务器上运行的任何测试都做了。

有什么想法吗?

c unit-testing testing malloc undefined-behavior
1个回答
0
投票

-fsanitize=undefined
使用 gcc 和 clang 捕获除以零的结果,无论优化级别如何。

尝试使用Godbolt。请注意,使用

-O3
,除法已优化为乘法,并且不执行
div
指令,因此不可能出现硬件被零除陷阱,但无论如何都会完成测试。

无论如何,这可能是比

-fsanitize=integer-divide-by-zero
更好的主意,因为它会捕获您可能没有想到的类型的 UB 的其他实例。

© www.soinside.com 2019 - 2024. All rights reserved.