C安全编程教学-声明和初始化-声明具有正确存储持续期的对象(一)_算法

注:本课程参考文献《C安全编码标准》

 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~

目录

一.介绍

二.不安全代码 

三.修改方案

四.练习与答案

4.1识别存储持续期

4.2避免悬挂指针

4.3理解存储持续期


一.介绍

    每个对象都拥有一个决定其生命周期的存储持续期,这些持续期可以是static(静态)、thread(线程)、automatic(自动)或allocated(动态分配)。

    对象的生命期是程序执行的一部分,在此期间保证为对象保留存储空间。对象在其生命期内存在,有固定的地址,保留最后存储的值。如果对象超出其生命期,则其行为未定义。当指针指向的对象生命期结束,则指针值无法确定。

二.不安全代码 

    在这个不兼容的代码例子中,变量c_str拥有自动存储期,意味着它的生命周期局限于定义它的代码块内。然而,这个变量的地址被赋给了另一个具有静态存储期的变量p。尽管这种赋值操作本身是允许的,但当dont_do_this()函数执行完毕后,c_str变量的生命周期结束,此时p中保存的地址便指向了一个不再有效的内存位置,因此p变得无效。

#include <stdio.h>
const char *p;
void dont_do_this(void){
    const char c_str[] = "This will change";
    p = c_str;
}
void innocuous(void){
    printf("%s\n",p);
}
int main(void) {
    dont_do_this();
    innocuous();
    return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

三.修改方案

    在这个兼容性的解决方案里,p被设定为与c_str具有相同的生命周期,这样做是为了防止在this_is_OK()函数之外,p取到不确定的值。

void this_is_OK(void) {
    const char c_str[] = "Everything OK";
    const char *p = c_str;
}
  • 1.
  • 2.
  • 3.
  • 4.

    或者,p和c_str都可声明为静态存储持续期。

    如果变量p被定义为具有静态存储持续期,而c_str使用的是相对有限的持续期,那么可以在c_str被销毁时将p设置为NULL。这样做可以避免p获取到不确定的值,但之后对p的任何引用都需要先检查是否为NULL

const char *p;
void is_this_OK(void){
    const char c_str[] = "Everything OK?";
    p = c_str;
    /* ... */
    p = NULL;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

四.练习与答案

4.1识别存储持续期

    以下代码段中,变量xy的存储持续期分别是什么?

void exampleFunction() {  
    int x = 10;  
    static int y = 20;  
}
  • 1.
  • 2.
  • 3.
  • 4.

答案

  • 变量x的存储持续期是automatic(自动)。
  • 变量y的存储持续期是static(静态)。

4.2避免悬挂指针

    修改以下代码,以避免悬挂指针问题。

#include <stdio.h>  
const char *p;  
  
void createString() {  
    char str[] = "Temporary String";  
    p = str;  
}  
  
void printString() {  
    printf("%s\n", p);  
}  
  
int main() {  
    createString();  
    printString();  
    return 0;  
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

答案

#include <stdio.h>  
  
void printString(const char *p) {  
    printf("%s\n", p);  
}  
  
int main() {  
    char str[] = "Temporary String";  
    printString(str);  
    return 0;  
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

    或者,如果需要使用全局变量p

#include <stdio.h>  
const char *p;  
  
void createString() {  
    static char str[] = "Temporary String";  
    p = str;  
}  
  
void printString() {  
    if (p != NULL) {  
        printf("%s\n", p);  
    } else {  
        printf("Pointer is NULL\n");  
    }  
}  
  
int main() {  
    createString();  
    printString();  
    return 0;  
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

4.3理解存储持续期

解释什么是自动存储持续期和静态存储持续期,并举例说明。

答案

  • 自动存储持续期:自动存储持续期的变量在定义它们的代码块执行时存在,当执行离开该代码块时,这些变量会被销毁。例如,函数内的局部变量。
void func() {  
    int x = 10; // x具有自动存储持续期  
}
  • 1.
  • 2.
  • 3.
  • 静态存储持续期:静态存储持续期的变量在程序执行期间一直存在,它们在程序开始执行时被创建,在程序结束时被销毁。例如,全局变量和静态变量。
static int y = 20; // y具有静态存储持续期
  • 1.

 非常感谢您花时间阅读我的博客,希望这些分享能为您带来启发和帮助。期待您的反馈与交流,让我们共同成长,再次感谢!

👇个人网站👇

 安城安的云世界

 

C安全编程教学-声明和初始化-声明具有正确存储持续期的对象(一)_算法_02