命名空间
变体
操作

生存期

来自 cppreference.cn
< c‎ | language

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++ 文档 关于 对象生命周期