生命周期
来自 cppreference.com
C 中的每个 对象 都存在,具有一个固定地址,并保留其最后存储的值(除非该值是不确定的),并且对于 VLA,保留其大小(自 C99) 在程序执行的某个部分,称为该对象的生命周期。
对于使用自动、静态和线程存储周期声明的对象,生命周期与其 存储周期 相同(注意非 VLA 和 VLA 自动存储周期的区别)。
对于具有分配存储周期的对象,生命周期从分配函数返回时开始(包括从 realloc 返回),并在调用 realloc 或释放函数时结束。请注意,由于分配的对象没有 声明的类型,因此用于访问该对象的左值表达式首先使用的类型将成为其 有效类型。
在对象生命周期之外访问对象会导致未定义行为。
int* foo(void) { int a = 17; // a has automatic storage duration return &a; } // lifetime of a ends int main(void) { int* p = foo(); // p points to an object past lifetime ("dangling pointer") int n = *p; // undefined behavior }
指向生命周期已结束的对象(或该对象之后的下一个对象)的指针具有不确定的值。
[编辑] 临时生命周期
具有数组成员(直接成员或嵌套结构体/联合体成员的成员)的结构体和联合体对象,这些成员由 非左值表达式 指定,具有临时生命周期。临时生命周期从引用该对象的表达式求值时开始,并在 下一个 序列点 处结束(直到 C11)包含的完整表达式或完整声明结束时结束(自 C11)。
任何尝试修改具有临时生命周期的对象都会导致未定义行为。
struct T { double a[4]; }; struct T f(void) { return (struct T){3.15}; } double g1(double* x) { return *x; } void g2(double* x) { *x = 1.0; } int main(void) { double d = g1(f().a); // C99: UB access to a[0] in g1 whose lifetime ended // at the sequence point at the start of g1 // C11: OK, d is 3.15 g2(f().a); // C99: UB modification of a[0] whose lifetime ended at the sequence point // C11: UB attempt to modify a temporary object }
[编辑] 参考
- C17 标准 (ISO/IEC 9899:2018)
- 6.2.4 对象的存储周期 (p: 30)
- C11 标准 (ISO/IEC 9899:2011)
- 6.2.4 对象的存储周期 (p: 38-39)
- C99 标准 (ISO/IEC 9899:1999)
- 6.2.4 对象的存储周期 (p: 32)
- C89/C90 标准 (ISO/IEC 9899:1990)
- 3.1.2.4 对象的存储周期
[编辑] 参见
C++ 文档 对象生命周期
|