自建网站费用,top的域名网站,青海做网站找谁,国际重大新闻事件10条文章目录 Intro如何正确认识 UB有多少未定义行为?对 UB 的误解 C 标准定义的几种行为1. 定义的行为 (defined behavior)2. 实现定义的行为 (implementation defined behavior)3. 未指定的行为 (unspecified behavior)4. 未定义行为 (undefined behavior)揭晓答案 C 中如何定义… 文章目录 Intro如何正确认识 UB有多少未定义行为?对 UB 的误解 C 标准定义的几种行为1. 定义的行为 (defined behavior)2. 实现定义的行为 (implementation defined behavior)3. 未指定的行为 (unspecified behavior)4. 未定义行为 (undefined behavior)揭晓答案 C 中如何定义 UBUB 不是错误 常见 C UB 的部分列表软件设计理念编译器选项对 UB 的影响当关闭编译器优化时通常会启用优化 如何消除 UBUB 举例带符号的整型溢出缺失 return 语句迭代器在使用时被破坏修改const reference类型值在std命名空间中增加代码求值顺序语法歧义 总结视频链接源码链接 Intro
在编程中我们会听到或者看到一个概念:“未定义行为(Undefined Behavior, 简称 UB)”. 什么是所谓的未定义行为, 会产生什么后果, 如何能避免? 本文将系统地探讨未定义行为的含义, 后果及规避方法
如何正确认识 UB
对未定义行为的字面理解就是: 这个行为没有被具体说明. 举个例子, 如果读到了 std::vectorT 的末尾会发生什么?
可能得结果有:
读取操作可能返回完全有效的 T或者可能返回非 T 的值程序可能在运行时崩溃读取操作可能会被编译器优化掉(删除掉)
因为根据 C 标准: reading past the end of std::vector is undefined behavior 读取超过 std::vector 末尾的内容是未定义的行为 因为没有做具体说明, 所以编译器可以做很多选择. 然而这些选择不一定是编写代码的程序员所期望的.
有多少未定义行为?
举个例子, 用 26 个英语字母作组合可以产生非常多单词. 排除掉字典里面定义的单词, 其他的单词可以被认为是未定义的, 可想而知这些未定义的情况非常多的. 同样的, C语言中的 UB 的具体 case 也会非常多, 不可枚举.
对 UB 的误解
一些常见的误解如下:
良好的测试将捕获 UB: 尽管测试可以帮助发现部分问题, 但由于测试覆盖率不足或测试环境与实际运行环境的差异, UB 可能在测试中未被触发. 例如, 某些 UB 仅在特定输入或硬件平台上显现, 因此良好的测试并不能保证捕获所有 UB.更好的编译器会将 UB 报告为错误: 编译器主要在静态分析范围内工作, 能检测的未定义行为是有限的. 许多 UB 需要在运行时动态触发, 例如特定输入条件或程序状态下才会显现, 这超出了编译器的检测能力.经验丰富的开发人员永远不会遇到糟糕的 UB调试 UB 只需要一点练习
后续的例子中我们将会消除这些迷思.
C 标准定义的几种行为
C标准中定义了如下几种行为:
1. 定义的行为 (defined behavior)
具有明确或精确含义的代码, 比如:
int sum 17 8;printf(Welcome to CppCon 2021);auto [first, second] getPair();
2. 实现定义的行为 (implementation defined behavior)
代码可以有多重含义, 但编译器必须选定一种并始终保持该选择. 请看下面的代码:
if ( sizeof(int) sizeof(long) ) { }C 标准中规定了int最小要有 16bit, long最小要有 32bit. 具体 bit 位数会因为编译器/操作系统而有所不同, 常见的编译器 GCC, Clang, MSVC 指定了 sizeof(int) 4, sizeof(long)
3. 未指定的行为 (unspecified behavior)
代码可能有多种含义, 编译器可以随机选择一个. 比如比较字符串字面量:
#include iostreamvoid fun(const char* key) {if (key name) {std::cout get name\n;} else {std::cout something else\n;}
}
int main() {std::string name name;fun(name); // output: get namefun(name.c_str()); // output: something elsereturn 0;
}比较字面量在实际中被实现为比较指针. 而程序员预期的应该是字符串比较.
4. 未定义行为 (undefined behavior)
毫无意义的代码, 比如:
两次调用对象的析构函数按负值进行位移位当值太大时将双精度数转换为浮点数
阅读下面的代码思考一下这两个问题:
下面的代码能通过编译吗?是否有 UB, 有的话指出具体行数.
#include iostreamint main() {int* p nullptr; // line 1*p 42; // line 2int b; // line 3p b; // line 4std::cout *p; // line 5std::cout b; // line 6
}揭晓答案
能通过编译有下面这些 UB ( line 2 ) 解析空指针是 UB( line 5 和 line 6) 访问一个未初始化的变量 UB
C 中如何定义 UB
所谓 UB 就是尝试去执行那种没有被 C标准明确说明其行为的代码.只有当源代码没有 UB 时, 程序会按源代码所写的执行如果你的代码有 UB, 那么 C 标准将对其执行结果不做任何保证编写没有 UB 的代码是程序员的责任
UB 不是错误
UB 和错误(Error)之间没有重叠被定义为错误的东西不是 UBUB 不是你的代码可以测试的东西
常见 C UB 的部分列表
访问 std::vector 末尾以外的元素解引用空指针使用未初始化的变量从构造函数或析构函数调用纯虚函数在对象被销毁后使用它(释放后使用)将指针转换为不兼容的类型, 然后使用无副作用的无限循环修改字符串文字或任何其他 const 对象无法从值返回函数返回值任何竞争条件整数除以零有符号整数溢出
软件设计理念
既然编译器可以做任何事情, 你不妨想象它会做一些坏事如果你的代码适用于所有当前的编译器, 那么你所做的任何事情都可能成为标准的一部分让人们以自己的方式尝试, 直到代码在测试期间崩溃对于那些关心速度的人来说, UB 应该只作为一种可选功能存在最终委员会将完成他们的工作并摆脱 UB程序员应该提供在他们的代码库中使用 UB 的合理理由
编译器选项对 UB 的影响
当关闭编译器优化时
几乎不会对您的代码进行任何特殊处理尽可能将您的代码翻译得接近字面意思未定义的行为可能会按照您的预期执行, 因此您的代码似乎按预期运行
通常会启用优化
可以删除无法访问的代码编译器无需诊断未定义的行为代码可以内联, 然后进行优化当程序具有未定义的行为时可能会产生意外结果
如何消除 UB 借助工具 Address SanitizerMemory SanitizerUndefined Behavior SanitizerThread Sanitizer 代码审查, 制定专门检查 UB 的政策 注意编译器警告 使用多个编译器构建代码 测试极端情况 将 UB 视为严重错误
UB 举例
带符号的整型溢出
有符号整数运算: 如果结果超出可表示值的范围, 则会发生有符号整数溢出, 这是未定义的行为无符号整数运算: 根据标准, 此操作永远不会溢出, 并且是定义的行为
#include iostreamtemplate typename T
T cubic(T len) {return len * len * len;
}int main() {std::cout cubic signed: cubic(3000) std::endl; // UBstd::cout cubic unsigned: cubic(3000u) std::endl; // OKreturn 0;
}缺失 return 语句
一些编译器会发出警告, 一些清理程序会在运行时检测到. 程序执行过程中的常见结果
可能导致崩溃每次都可能返回 true可能会继续执行可执行文件中的下一个函数
#include iostreambool baz() { return true; }
bool foo(int a, int b) { a b; }
bool bar() { return false; }int main() {int a 1;int b 2;std::cout a b: foo(a, b) std::endl;std::cout bar() baz() std::endl;return 0;
}迭代器在使用时被破坏
容器上的某些操作会使迭代器无效, std::vector::insert() 使所有迭代器无效.
基于范围的 for 循环中的迭代器被隐藏当前迭代器在 insert 之后被破坏
#include iostream
#include vectorint main() {std::vectorint vec {1, 2, 3, 5, 6};for (auto item : vec) {if (item 3) {vec.insert(vec.begin(), 4);}std::cout item std::endl;}return 0;
}修改const reference类型值
关键字 const_cast 删除对象的常量性, 如果传递的参数最初被声明为 const, 则修改输入是未定义的行为
#include iostream
#include stringconst std::string global Hello;void fun(const std::string input) {std::string v const_caststd::string (input);v fun;
}int main() {const std::string local World;fun(local);std::cout local std::endl;fun(global);std::cout global std::endl;return 0;
}在std命名空间中增加代码
偏特化 std 命名空间中存在的类型特征是 UB. 编写自己的类型特征是完全可以接受的, 它们可以 位于除 std:: 之外的任何命名空间中.
#include iostream
#include type_traitsnamespace std {
template
struct is_pointerint : public std::true_type // defines a type trait as true
{};
} // namespace stdint main() {bool var2 std::is_pointerint::value;std::cout std::boolalpha std::is_pointerint::value std::endl;return 0;
}求值顺序
#include iostreamint main() {int a 5;a a 2; // C03, undefined behaviora 8; // C11 and newer, definedstd::cout a: a std::endl;int b 3;b b 2; // C03 and C11, undefined behaviorb 5; // C17 and newer, definedstd::cout b: b std::endl;
}语法歧义
这个函数有未定义的行为吗?
#include iostreamtemplate typename T1, typename T2
void fun(T1 x, T2 y) {x y;
}int main() {int a 1;int b 1000;fun(a, b); // UB: 左移操作的移动位数超过了类型的宽度fun(std::cout, cat); // OK
}我们看到这个例子中是否有 UB 取决于入参, 以及入参的具体值.
C 为了更明确模板的行为, 推出了新特性Concept概念, 用来约束模板参数. 方便开发者避免此类问题.
总结
UB 不能被视为错误处理 UB 并非是一个间歇性工作, 需要一直坚持UB 不是一个简单的话题项目可以选择关闭 C 特性(如异常), 但你不能关闭 UB处理 UB 是每个开发人员的责任, 选择 C 就等于接受了它
视频链接
Back To Basics: Undefined Behavior - Ansel Sermersheim Barbara Geller - CppCon 2021
源码链接
源码链接 文章转载自: http://www.morning.hxlpm.cn.gov.cn.hxlpm.cn http://www.morning.gyfhk.cn.gov.cn.gyfhk.cn http://www.morning.kfwqd.cn.gov.cn.kfwqd.cn http://www.morning.jgnst.cn.gov.cn.jgnst.cn http://www.morning.kpcxj.cn.gov.cn.kpcxj.cn http://www.morning.yrck.cn.gov.cn.yrck.cn http://www.morning.yodajy.cn.gov.cn.yodajy.cn http://www.morning.xkzr.cn.gov.cn.xkzr.cn http://www.morning.sxfnf.cn.gov.cn.sxfnf.cn http://www.morning.cbvlus.cn.gov.cn.cbvlus.cn http://www.morning.hgkbj.cn.gov.cn.hgkbj.cn http://www.morning.nthyjf.com.gov.cn.nthyjf.com http://www.morning.crfyr.cn.gov.cn.crfyr.cn http://www.morning.kpxnz.cn.gov.cn.kpxnz.cn http://www.morning.klzdy.cn.gov.cn.klzdy.cn http://www.morning.rwdbz.cn.gov.cn.rwdbz.cn http://www.morning.ncqzb.cn.gov.cn.ncqzb.cn http://www.morning.ryywf.cn.gov.cn.ryywf.cn http://www.morning.8yitong.com.gov.cn.8yitong.com http://www.morning.sjftk.cn.gov.cn.sjftk.cn http://www.morning.pbmkh.cn.gov.cn.pbmkh.cn http://www.morning.yrbq.cn.gov.cn.yrbq.cn http://www.morning.psyrz.cn.gov.cn.psyrz.cn http://www.morning.ymjgx.cn.gov.cn.ymjgx.cn http://www.morning.kxbry.cn.gov.cn.kxbry.cn http://www.morning.lqjlg.cn.gov.cn.lqjlg.cn http://www.morning.sqqkr.cn.gov.cn.sqqkr.cn http://www.morning.lnbyk.cn.gov.cn.lnbyk.cn http://www.morning.zrdhd.cn.gov.cn.zrdhd.cn http://www.morning.mlmwl.cn.gov.cn.mlmwl.cn http://www.morning.jkzjs.cn.gov.cn.jkzjs.cn http://www.morning.qrgfw.cn.gov.cn.qrgfw.cn http://www.morning.ghxkm.cn.gov.cn.ghxkm.cn http://www.morning.rfkyb.cn.gov.cn.rfkyb.cn http://www.morning.plhyc.cn.gov.cn.plhyc.cn http://www.morning.nlywq.cn.gov.cn.nlywq.cn http://www.morning.nlgnk.cn.gov.cn.nlgnk.cn http://www.morning.sgfpn.cn.gov.cn.sgfpn.cn http://www.morning.klltg.cn.gov.cn.klltg.cn http://www.morning.lczxm.cn.gov.cn.lczxm.cn http://www.morning.mtbth.cn.gov.cn.mtbth.cn http://www.morning.dodoking.cn.gov.cn.dodoking.cn http://www.morning.kdldx.cn.gov.cn.kdldx.cn http://www.morning.nfccq.cn.gov.cn.nfccq.cn http://www.morning.gswfs.cn.gov.cn.gswfs.cn http://www.morning.ycnqk.cn.gov.cn.ycnqk.cn http://www.morning.bnrff.cn.gov.cn.bnrff.cn http://www.morning.ctlzf.cn.gov.cn.ctlzf.cn http://www.morning.sjwws.cn.gov.cn.sjwws.cn http://www.morning.ckrnq.cn.gov.cn.ckrnq.cn http://www.morning.lmhwm.cn.gov.cn.lmhwm.cn http://www.morning.sgcdr.com.gov.cn.sgcdr.com http://www.morning.crqpl.cn.gov.cn.crqpl.cn http://www.morning.pmdnx.cn.gov.cn.pmdnx.cn http://www.morning.rzbgn.cn.gov.cn.rzbgn.cn http://www.morning.muzishu.com.gov.cn.muzishu.com http://www.morning.mrcpy.cn.gov.cn.mrcpy.cn http://www.morning.yltnl.cn.gov.cn.yltnl.cn http://www.morning.rbxsk.cn.gov.cn.rbxsk.cn http://www.morning.mfzyn.cn.gov.cn.mfzyn.cn http://www.morning.xtkw.cn.gov.cn.xtkw.cn http://www.morning.fjzlh.cn.gov.cn.fjzlh.cn http://www.morning.fstesen.com.gov.cn.fstesen.com http://www.morning.bhdtx.cn.gov.cn.bhdtx.cn http://www.morning.zcqtr.cn.gov.cn.zcqtr.cn http://www.morning.zglrl.cn.gov.cn.zglrl.cn http://www.morning.rxgnn.cn.gov.cn.rxgnn.cn http://www.morning.dwmtk.cn.gov.cn.dwmtk.cn http://www.morning.fdfdz.cn.gov.cn.fdfdz.cn http://www.morning.rlwcs.cn.gov.cn.rlwcs.cn http://www.morning.rwzc.cn.gov.cn.rwzc.cn http://www.morning.touziyou.cn.gov.cn.touziyou.cn http://www.morning.fhtbk.cn.gov.cn.fhtbk.cn http://www.morning.mlcwl.cn.gov.cn.mlcwl.cn http://www.morning.bsjpd.cn.gov.cn.bsjpd.cn http://www.morning.jkdtz.cn.gov.cn.jkdtz.cn http://www.morning.gfqj.cn.gov.cn.gfqj.cn http://www.morning.cklgf.cn.gov.cn.cklgf.cn http://www.morning.mhmdx.cn.gov.cn.mhmdx.cn http://www.morning.swkpq.cn.gov.cn.swkpq.cn