qsort传入n=0是否为C未定义行为?gcc编译误报问题解析
我收到一份未亲自验证但来源可靠的报告称,代码:
qsort(a, n, sizeof *a, cmpfunc);
被现代版本的gcc编译后,等效于:
if(n == 0) __builtin_trap(); qsort(a, n, sizeof *a, cmpfunc);
显然有人认为调用qsort时传入n==0属于未定义行为。
[编辑:后续发现整个前提不成立,详见下方“更新2”]
有人指出Posix明确认可n==0的情况,但现有C标准似乎并未明确规定。
由此引出以下问题:
- 在C语言中,调用
qsort时传入n=0是否确实属于未定义行为? - 所有调用
qsort时n值不确定的程序是否必须先检查n==0,再决定是否调用qsort? - gcc为何要执行这种“优化”?即便认为
n==0时调用qsort是未定义行为,这也会略微拖慢所有合规程序的运行速度。
尽管qsort不一定是教科书式的快速排序实现,但这类实现基本都能正确处理n=0的情况。我不禁疑惑,gcc的这种行为是否是为了防范某些qsort实现在初始调用n==0时出现比__builtin_trap更严重的问题?
更新:感谢各位的回复。~~看起来gcc的做法有误。~~如前所述,我尚未亲自验证该结果,目前正试图确认观察到该问题的gcc版本及使用的优化标志。
更新2:我引用的原始报告存在错误,核心澄清如下:
- gcc实际检查的是
a==0,而非n==0。这显然完全不同:正如本讨论及其他线程所确认的,传入空指针调用qsort的问题大得多,几乎可以肯定属于正式定义的未定义行为。 - 编译时使用了
-fsanitize=undefined和-fsanitize-undefined-trap-on-error标志,因此gcc必然会严格检查意外的空指针(即便会牺牲效率)。
抱歉带来错误信息和困扰。该问题现已属于“无法复现或由输入错误导致”,我已发起关闭投票。
补充说明:涉及的gcc版本为12.2.1。
内容的提问来源于stack exchange,提问作者Steve Summit
相关产品推荐
相关产品推荐

