线程安全(Thread Safety) 类型安全(Type Safety) 内存安全(Memory Safety) 异常安全(Exception Safety) 并发安全(Concurrency Safety) 资源安全(Resource Safety) 边界安全(Bounds Safety)
线程安全(Thread Safety)
不安全示例:
#include <iostream>
#include <thread>
int counter = 0;
void increment() {
for (int i = 0; i < 100000; ++i) {
counter++; // 多个线程同时修改共享变量,导致数据竞争
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << "Counter: " << counter << std::endl; // 结果可能小于 200000
return 0;
} 问题:多个线程同时修改counter,导致数据竞争,结果不确定。
线程安全改进:
#include <iostream>
#include <thread>
#include <mutex>
int counter = 0;
std::mutex mtx;
void increment() {
for (int i = 0; i < 100000; ++i) {
std::lock_guard<std::mutex> lock(mtx); // 使用互斥锁保护共享资源
counter++;
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << "Counter: " << counter << std::endl; // 结果一定是 200000
return 0;
} 改进:使用std::mutex保护共享变量,确保线程安全。
类型安全(Type Safety)
不安全示例:
#include <iostream>
int main() {
double value = 3.14;
int* ptr = (int*)&value; // C风格强制类型转换,破坏了类型安全
std::cout << *ptr << std::endl; // 未定义行为
return 0;
} 问题:C风格强制类型转换可能导致未定义行为。
类型安全改进:
#include <iostream>
int main() {
double value = 3.14;
int intValue = static_cast<int>(value); // 使用安全的类型转换
std::cout << intValue << std::endl; // 输出 3
return 0;
} 改进:使用static_cast进行安全的类型转换。
内存安全(Memory Safety)
不安全示例:
#include <iostream>
int main() {
int* ptr = new int(10);
delete ptr;
std::cout << *ptr << std::endl; // 访问已释放的内存,悬空指针
return 0;
} 问题:访问已释放的内存,导致未定义行为。
内存安全改进:
#include <iostream>
#include <memory>
int main() {
auto ptr = std::make_unique<int>(10); // 使用智能指针管理内存
std::cout << *ptr << std::endl; // 输出 10
// 不需要手动释放内存,智能指针会自动释放
return 0;
} 改进:使用std::unique_ptr管理内存,避免悬空指针。
异常安全(Exception Safety)
不安全示例:
#include <iostream>
void unsafeFunction() {
int* ptr = new int(10);
throw std::runtime_error("Error!"); // 抛出异常
delete ptr; // 不会执行,导致内存泄漏
}
int main() {
try {
unsafeFunction();
} catch (const std::exception& e) {
std::cout << e.what() << std::endl;
}
return 0;
} 问题:抛出异常时,资源未释放,导致内存泄漏。
异常安全改进:
#include <iostream>
#include <memory>
void safeFunction() {
auto ptr = std::make_unique<int>(10); // 使用智能指针
throw std::runtime_error("Error!"); // 抛出异常
// 不需要手动释放内存,智能指针会自动释放
}
int main() {
try {
safeFunction();
} catch (const std::exception& e) {
std::cout << e.what() << std::endl;
}
return 0;
} 改进:使用智能指针确保资源在异常发生时自动释放。
并发安全(Concurrency Safety)
不安全示例:
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx1;
std::mutex mtx2;
void thread1() {
std::lock_guard<std::mutex> lock1(mtx1);
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟耗时操作
std::lock_guard<std::mutex> lock2(mtx2); // 可能导致死锁
}
void thread2() {
std::lock_guard<std::mutex> lock2(mtx2);
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟耗时操作
std::lock_guard<std::mutex> lock1(mtx1); // 可能导致死锁
}
int main() {
std::thread t1(thread1);
std::thread t2(thread2);
t1.join();
t2.join();
std::cout << "Done" << std::endl;
return 0;
} 问题:两个线程互相等待对方释放锁,导致死锁。
并发安全改进:
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx1;
std::mutex mtx2;
void thread1() {
std::lock(mtx1, mtx2); // 同时锁定多个互斥锁,避免死锁
std::lock_guard<std::mutex> lock1(mtx1, std::adopt_lock);
std::lock_guard<std::mutex> lock2(mtx2, std::adopt_lock);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
void thread2() {
std::lock(mtx1, mtx2); // 同时锁定多个互斥锁,避免死锁
std::lock_guard<std::mutex> lock1(mtx1, std::adopt_lock);
std::lock_guard<std::mutex> lock2(mtx2, std::adopt_lock);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
int main() {
std::thread t1(thread1);
std::thread t2(thread2);
t1.join();
t2.join();
std::cout << "Done" << std::endl;
return 0;
} 改进:使用std::lock同时锁定多个互斥锁,避免死锁。
资源安全(Resource Safety)
不安全示例:
#include <iostream>
#include <fstream>
void unsafeFunction() {
std::ofstream file("test.txt");
file << "Hello, World!" << std::endl;
throw std::runtime_error("Error!"); // 抛出异常
file.close(); // 不会执行,导致文件句柄泄漏
}
int main() {
try {
unsafeFunction();
} catch (const std::exception& e) {
std::cout << e.what() << std::endl;
}
return 0;
} 问题:抛出异常时,文件句柄未关闭,导致资源泄漏。
资源安全改进:
#include <iostream>
#include <fstream>
void safeFunction() {
std::ofstream file("test.txt");
file << "Hello, World!" << std::endl;
throw std::runtime_error("Error!"); // 抛出异常
// 不需要手动关闭文件,RAII 会自动关闭
}
int main() {
try {
safeFunction();
} catch (const std::exception& e) {
std::cout << e.what() << std::endl;
}
return 0;
} 改进:利用RAII机制,文件在作用域结束时自动关闭。
边界安全(Bounds Safety)
不安全示例:
#include <iostream>
int main() {
int arr[3] = {1, 2, 3};
std::cout << arr[5] << std::endl; // 越界访问,未定义行为
return 0;
} 问题:访问数组越界,导致未定义行为。
边界安全改进:
#include <iostream>
#include <vector>
int main() {
std::vector<int> arr = {1, 2, 3};
if (arr.size() > 5) {
std::cout << arr[5] << std::endl; // 检查边界
} else {
std::cout << "Out of bounds!" << std::endl;
}
return 0;
} 改进:使用std::vector并检查边界,避免越界访问。