我有一个作业,其中我必须编写自己的 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
进行编译,并且在运行时没有产生任何错误。
我知道根据定义,未定义的行为是未定义的,因此没有真正的方法来检测它,但似乎后端服务器上运行的任何测试都做了。
有什么想法吗?
-fsanitize=undefined
使用 gcc 和 clang 捕获除以零的结果,无论优化级别如何。
尝试使用Godbolt。请注意,使用
-O3
,除法已优化为乘法,并且不执行 div
指令,因此不可能出现硬件被零除陷阱,但无论如何都会完成测试。
无论如何,这可能是比
-fsanitize=integer-divide-by-zero
更好的主意,因为它会捕获您可能没有想到的类型的 UB 的其他实例。