[C++] 전역 변수의 몇 가지 잠재적인 문제

머리말:

        C++는 프로그래머가 전역 변수를 정의하고 사용할 수 있도록 하는 매우 일반적으로 사용되는 프로그래밍 언어입니다. 전역 변수는 프로그램에서 광범위하게 사용되지만 접근이 전역적이기 때문에 몇 가지 잠재적인 문제를 일으킬 수 있습니다. 이 기사에서는 C++ 전역 변수에 대한 계측 기능 향상에 대해 논의하고 몇 가지 가능한 문제와 솔루션에 대해 논의하며 몇 가지 실용적인 예를 제공합니다.

첫째, 전역 변수의 정의와 사용

        C++의 전역 변수는 함수 외부에서 정의할 수 있으므로 전역 범위를 제공합니다. 이 경우 전역 변수는 정의된 함수뿐만 아니라 전체 프로그램에서 볼 수 있습니다.

전역 변수는 다음과 같이 정의됩니다.

int global_var = 10;

        전역 변수를 정의한 후에는 프로그램 어디에서나 액세스할 수 있습니다. 예를 들어 함수에서 다음을 사용하여 이 전역 변수에 액세스할 수 있습니다.

void foo(){
    std::cout << global_var << std::endl;
}

        이 예제에서는 전역 변수 global_var에 액세스할 수 있는 함수 foo()를 정의합니다.

둘째, C++ 전역 변수의 문제

        전역 변수는 완전히 무해하지 않습니다. 전역 변수에는 전역 범위가 있으므로 모든 코드에서 수정할 수 있습니다. 이로 인해 다음과 같은 몇 가지 잠재적인 문제가 발생할 수 있습니다.

1. 네임스페이스 오염

        전역 변수가 정의되면 변수 이름은 전체 프로그램 이름 공간의 일부가 됩니다. 따라서 프로그램에 여러 전역 변수가 존재하면 이름이 중복되어 네임스페이스 오염이 발생할 수 있습니다. 이것은 코드를 유지하기 어렵게 만들 수 있습니다.

네임스페이스 오염 사례 코드:

// 文件1:global_var1.cpp
int global_var = 0;

// 文件2:global_var2.cpp
int global_var = 1;

// main.cpp
#include <iostream>

int main(){
    std::cout << global_var << std::endl;  // 编译错误:multiple definition of 'global_var'
    return 0;
}

        이 코드에서는 두 개의 다른 파일(global_var1.cpp 및 global_var2.cpp)에 동일한 이름을 가진 두 개의 전역 변수를 정의합니다. main.cpp에서 이러한 전역 변수에 액세스하려고 시도하지만 동일한 이름을 가진 여러 전역 변수가 있기 때문에 링크 오류가 발생합니다.

2. 프로그램 보안 문제

        전역 변수는 프로그램의 어디에서나 액세스할 수 있으므로 일부 보안 문제가 발생할 수 있습니다. 예를 들어 전역 변수가 암호와 같은 민감한 정보를 저장하는 경우 프로그램의 모든 사용자가 해당 정보에 액세스하고 수정할 수 있습니다.

프로그램 보안 문제 사례 코드:

#include <iostream>
#include <string>

// 存储用户密码的全局变量
std::string password = "12345678";

// 函数1:读取密码
void read_password(){
    std::string input_password;
    std::cout << "请输入密码:" << std::endl;
    std::cin >> input_password;
    if(input_password == password){
        std::cout << "密码正确" << std::endl;
    } else{
        std::cout << "密码错误" << std::endl;
    }
}

// 函数2:修改密码
void change_password(){
    std::string new_password;
    std::cout << "请输入新密码:" << std::endl;
    std::cin >> new_password;
    password = new_password;
    std::cout << "密码修改成功" << std::endl;
}

// main函数
int main(){
    read_password();
    change_password();
    read_password();
    return 0;
}

        이 코드에서는 전역 변수(암호)를 사용하여 사용자의 암호를 저장합니다. 비밀번호를 읽고 비밀번호를 변경하는 두 가지 기능(read_password 및 change_password)을 각각 정의합니다. 전역 변수는 프로그램의 어디에서나 액세스할 수 있으므로 이 암호는 어디에서나 읽고 수정할 수 있으므로 보안 위험이 있습니다.

3. 멀티스레딩 문제

        전역 변수는 멀티스레딩 문제를 일으킬 수도 있습니다. 여러 스레드가 전역 변수에 동시에 액세스하고 수정하는 경우 경합 상태 및 교착 상태가 발생할 수 있습니다.

멀티스레딩 문제 사례 코드:

#include <iostream>
#include <thread>

// 全局变量
int global_var = 0;

// 线程1:不断增加全局变量
void thread1(){
    for(int i = 0; i < 100000; i++){
        global_var++;
    }
}

// 线程2:不断减少全局变量
void thread2(){
    for(int i = 0; i < 100000; i++){
        global_var--;
    }
}

// main函数
int main(){
    std::thread t1(thread1);
    std::thread t2(thread2);

    t1.join();
    t2.join();

    std::cout << "global_var = " << global_var << std::endl;  // 输出:global_var = -4629

    return 0;
}

        이 코드에서는 전역 변수(global_var)를 각각 계속 증가 및 감소시키는 두 개의 스레드(thread1 및 thread2)를 정의합니다. 두 스레드가 동시에 전역 변수에 액세스하고 수정하기 때문에 경쟁 조건과 교착 상태가 발생할 수 있습니다.

3. C++ 전역 변수 감지 기능 향상

        이러한 가능한 문제를 해결하기 위해 다음 측면을 포함하여 몇 가지 향상된 감지 방법을 사용할 수 있습니다.

1. 네임스페이스에 전역 변수 정의

        네임스페이스에서 전역 변수를 정의하면 전역 변수가 다른 변수와 동일한 이름을 갖는 것을 방지할 수 있습니다. 예를 들어:

namespace my_namespace{
    int global_var = 10;
}

        이런 식으로 프로그램 전체에서 my_namespace::global_var이 전역 변수에 .

2. 변경 불가능한 전역 변수 대신 상수 사용

        전역 변수의 값을 수정하지 않으려면 정의할 때 상수를 대신 사용하는 것이 좋습니다. 예를 들어:

const int global_const_var = 10;

        이 예제에서는 상수를 사용하여 전역 변수를 정의합니다. 상수이기 때문에 변경할 수 없으므로 코드가 더 안전합니다.

3. 글로벌 변수 대신 로컬 변수 사용

        경우에 따라 전역 변수 대신 지역 변수를 사용할 수 있습니다. 변수가 하나의 함수에서만 사용되는 경우 전역 변수를 정의하는 대신 이 함수에서 로컬 변수를 정의할 수 있습니다. 예를 들어:

void foo(){
    int local_var = 10;
    std::cout << local_var << std::endl;
}

        이 예에서는 전역 변수를 정의하는 대신 로컬 변수 local_var를 정의합니다.

4. 캡슐화 메커니즘 사용

        전역 변수를 프로그램의 여러 위치에서 사용해야 하는 경우 캡슐화 메커니즘을 사용하는 것이 좋습니다. 캡슐화 메커니즘을 사용하면 전역 변수 및 관련 함수를 클래스에 캡슐화할 수 있습니다. 이 접근 방식은 클래스의 멤버 함수만 전역 변수에 액세스할 수 있도록 합니다. 예를 들어:

class GlobalVar{
public:
    static int get_global_var(){
        return global_var;
    }

private:
    static int global_var;
};

int GlobalVar::global_var = 10;

void foo(){
    std::cout << GlobalVar::get_global_var() << std::endl;
}

        이 예제에서는 정적 멤버 변수 global_var 및 정적 멤버 함수 get_global_var()를 포함하는 GlobalVar 클래스를 정의합니다. 정적 멤버 변수 및 함수를 사용하면 클래스의 멤버 함수만 전역 변수에 액세스할 수 있습니다.

5. 싱글톤 패턴 사용

        싱글톤 패턴은 클래스의 인스턴스가 하나만 있도록 하는 디자인 패턴입니다. 프로그램의 여러 위치에서 전역 변수를 사용해야 하고 인스턴스가 하나만 있는지 확인해야 하는 경우 싱글톤 패턴을 사용할 수 있습니다. 예를 들어:

class GlobalVar{
public:
    static GlobalVar* instance(){
        static GlobalVar gv;
        return &gv;
    }

    int get_global_var(){
        return global_var;
    }

private:
    GlobalVar(){
        global_var = 10;
    }

    int global_var;
};

void foo(){
    std::cout << GlobalVar::instance()->get_global_var() << std::endl;
}

        이 예제에서는 GlobalVar 클래스를 정의하고 싱글톤 패턴을 사용하여 인스턴스가 하나만 있는지 확인합니다. 생성자에서 전역 변수 global_var를 초기화합니다. 싱글톤 패턴을 사용하여 인스턴스가 하나만 있는지 확인하고 get_global_var() 함수를 사용하여 클래스의 멤버 함수만 전역 변수에 액세스할 수 있도록 합니다.

요약하다:

        C++의 전역 변수는 몇 가지 잠재적인 문제를 일으킬 수 있습니다. 이러한 문제를 해결하기 위해 전역 변수를 네임스페이스에 정의하고, 불변 전역 변수 대신 상수를 사용하고, 전역 변수 대신 지역 변수를 사용하고, 캡슐화 메커니즘을 사용하고, 싱글톤 모드를 사용하는 등 향상된 감지 방법을 사용할 수 있습니다 . 위의 계획은 특정 상황에 따라 사용할 수 있습니다.

추천

출처blog.csdn.net/crr411422/article/details/130982443