开发公司 网站建设价格做织梦网站的心得体会
实验项目:任务3
任务1和任务2基础上改写 SecureBuffer 类,完成安全编程,使用 Valgrind/AddressSanitizer或其他代码检测工具检测问题:
手动编写函数,实现 SafeDelete(T& ptr)*
功能点:
清空内存内容(如 memset(ptr, 0, size))
安全释放 delete
自动置空,避免悬垂指针
防止重复释放
拷贝构造更改为移动构造
为 SecureBuffer 类增加移动构造函数和移动赋值运算符
使用智能指针优化代码,降低悬垂指针风险,彻底杜绝手动 delete,更安全
使用 std::unique_ptr 管理 SecureBuffer
用 std::shared_ptr 进行引用计数(新增)
引入容器存储 std::shared_ptr,进行资源管理
功能点
使用 std::vector<std::shared_ptr<SecureBuffer>> 统一管理多个 SecureBuffer
确保对象在所有引用结束后自动释放
输出容器内容,观察 shared_ptr 的引用计数
测试要求(利用任务1的打印方法打印出内存内容):
- 使用 SafeDelete 测试
- 调用SecureBuffer类的修改方法(在任务1中已经实现),修改对象,之后进行移动构造测试移动语义
- 使用 std::unique_ptr 进行内存管理
- 使用 std::shared_ptr 进行共享引用管理
- 使用 std::vector 容器存储 shared_ptr
提交:
1. 代码(c++)
2. 测试用例
3. 过程及结果截图
4. 文字分析,要求:回顾和内存管理相关的3次实验内容,可以从这个角度进行总结:
手动管理内存(new/delete包括构造析构和分配释放)-> SafeDelete
拷贝构造 -> 移动构造
裸指针 -> 智能指针(unique_ptr、shared_ptr)
容器
目录
实验项目:任务3
实验步骤、实验结果及结果分析:
1. SafeDelete 实现
初始实现
添加内存清空
显式调用析构函数
2. 移动语义实现
添加移动构造函数和移动赋值运算符
3. 智能指针使用
使用 std::unique_ptr
4. 容器管理
提交:
1. 代码(c++)
2. 测试用例
3. 过程及结果截图
4. 文字分析
实验步骤、实验结果及结果分析:
// 原始代码
#include<iostream>
#include<cstring>
class SecureBuffer{private:char* m_data;size_t m_size;public:SecureBuffer(size_t size):m_size(size){m_data=new char[m_size];memset(m_data,0xCC,m_size);}~SecureBuffer(){memset(m_data,0x00,m_size);delete[] m_data;}void print_data(){for(size_t i=0;i<m_size;++i){std::cout<<std::hex<<(int)m_data[i]<<" ";}std::cout<<std::endl;}char* get_data(){return m_data;}};
int main(){// 1SecureBuffer* buffer=new SecureBuffer(10);std::cout << "After construction: ";buffer->print_data();buffer->~SecureBuffer();std::cout << "After explicit destruction: ";buffer->print_data();// 2std::cout << "Trying to read after destruction: ";std::cout<<std::hex<<(int)buffer->get_data()[0]<<std::endl;std::cout << "Trying to modify after destruction: ";buffer->get_data()[0]=0xFF;buffer->print_data();// 3operator delete(buffer);std::cout << "After operator delete: ";std::cout << std::hex << (int)buffer->get_data()[0] << std::endl;
}
#include <iostream>
#include <cstring>
#include <vector>
#include <memory> // 引入智能指针头文件class SecureBuffer {
private:std::unique_ptr<char[]> m_data; // 使用智能指针管理内存size_t m_size;public:// 构造函数SecureBuffer(size_t size) : m_size(size), m_data(std::make_unique<char[]>(m_size)) {std::memset(m_data.get(), 0xCC, m_size);}// 析构函数(无需手动释放内存)~SecureBuffer() {std::memset(m_data.get(), 0x00, m_size); // 清空内存为 0x00}// 打印数据void print_data() const {for (size_t i = 0; i < m_size; ++i) {std::cout << std::hex << (int)m_data[i] << " ";}std::cout << std::endl;}
};int main() {std::vector<std::unique_ptr<SecureBuffer>> buffers; // 使用智能指针for (int i = 0; i < 10000; ++i) {buffers.push_back(std::make_unique<SecureBuffer>(10)); // 自动管理内存}std::cout << "Created 10000 SecureBuffer objects with smart pointers." << std::endl;return 0; // 程序退出时,智能指针会自动释放内存
}
1. SafeDelete 实现
手动编写函数,实现 SafeDelete(T& ptr)*
功能点:
清空内存内容(如 memset(ptr, 0, size))
安全释放 delete
自动置空,避免悬垂指针
防止重复释放
初始实现
- 自动置空指针,避免悬垂指针
- 防止重复释放(通过检查指针是否为 null)
template<typename T>
void SafeDelete(T*& ptr) {if (ptr != nullptr) {delete ptr;ptr = nullptr;}
}
添加内存清空
template<typename T>
void SafeDelete(T*& ptr) {if (ptr != nullptr) {// 清空内存内容memset(ptr, 0, sizeof(T));delete ptr;ptr = nullptr;}
}
显式调用析构函数
template<typename T>
void SafeDelete(T*& ptr) {if (ptr != nullptr) {// 显式调用析构函数ptr->~T();// 清空内存内容memset(ptr, 0, sizeof(T));// 使用 operator delete 释放内存::operator delete(ptr);ptr = nullptr;}
}
实现了 SafeDelete 模板函数,具有以下安全特性:
- 清空内存内容(使用 memset)
- 安全释放内存(先调用析构函数,再 operator delete)
- 自动置空指针,避免悬垂指针
- 防止重复释放(通过检查指针是否为 null)
2. 移动语义实现
拷贝构造更改为移动构造
为 SecureBuffer 类增加移动构造函数和移动赋值运算符
class SecureBuffer {
public:SecureBuffer(size_t size) : size_(size), data_(new uint8_t[size]) {}~SecureBuffer() {if (data_) {memset(data_, 0, size_);delete[] data_;data_ = nullptr;size_ = 0;}}// 禁用拷贝构造和拷贝赋值SecureBuffer(const SecureBuffer&) = delete;SecureBuffer& operator=(const SecureBuffer&) = delete;private:size_t size_;uint8_t* data_;
};
添加移动构造函数和移动赋值运算符
class SecureBuffer {
public:// ... 原有构造函数和析构函数 ...// 移动构造函数SecureBuffer(SecureBuffer&& other) noexcept : size_(other.size_), data_(other.data_) {other.size_ = 0;other.data_ = nullptr;}// 移动赋值运算符SecureBuffer& operator=(SecureBuffer&& other) noexcept {if (this != &other) {// 清理当前对象资源if (data_) {memset(data_, 0, size_);delete[] data_;}// 转移资源所有权size_ = other.size_;data_ = other.data_;// 置空源对象other.size_ = 0;other.data_ = nullptr;}return *this;}private:size_t size_;uint8_t* data_;
};
为 SecureBuffer 类增加了:
- 移动构造函数:转移资源所有权,将源对象置空
- 移动赋值运算符:安全转移资源,先清理当前对象资源
- 禁用拷贝构造和拷贝赋值(= delete)
3. 智能指针使用
使用智能指针优化代码,降低悬垂指针风险,彻底杜绝手动 delete,更安全
使用 std::unique_ptr 管理 SecureBuffer
用 std::shared_ptr 进行引用计数(新增)
使用 std::unique_ptr
void demoUniquePtr() {// 创建 unique_ptr 管理的 SecureBufferstd::unique_ptr<SecureBuffer> buffer(new SecureBuffer(1024));// 转移所有权std::unique_ptr<SecureBuffer> buffer2 = std::move(buffer);// buffer 现在为空assert(buffer == nullptr);// 自动释放,无需手动调用 delete
}
使用 std::shared_ptr 和 std::make_shared
void demoSharedPtr() {// 使用 make_shared 创建 shared_ptrauto buffer1 = std::make_shared<SecureBuffer>(1024);{// 共享所有权auto buffer2 = buffer1;// 引用计数为2assert(buffer1.use_count() == 2);}// buffer2 离开作用域,引用计数减为1assert(buffer1.use_count() == 1);// 自动释放,当最后一个引用消失时
}
- 使用
std::unique_ptr管理 SecureBuffer,确保独占所有权和自动释放 - 使用
std::shared_ptr实现引用计数,允许多个所有者共享资源 - 使用
std::make_shared创建 shared_ptr,更高效且安全
4. 容器管理
引入容器存储 std::shared_ptr,进行资源管理
功能点
使用 std::vector<std::shared_ptr<SecureBuffer>> 统一管理多个 SecureBuffer
确保对象在所有引用结束后自动释放
输出容器内容,观察 shared_ptr 的引用计数
使用 vector 管理 shared_ptr
void demoContainer() {std::vector<std::shared_ptr<SecureBuffer>> buffers;// 添加几个 SecureBufferbuffers.push_back(std::make_shared<SecureBuffer>(256));buffers.push_back(std::make_shared<SecureBuffer>(512));buffers.push_back(std::make_shared<SecureBuffer>(1024));// 观察引用计数auto buffer = buffers[0];std::cout << "Reference count: " << buffer.use_count() << std::endl; // 2{auto localCopy = buffer;std::cout << "Reference count: " << buffer.use_count() << std::endl; // 3}std::cout << "Reference count: " << buffer.use_count() << std::endl; // 2// 从容器中移除buffers.erase(buffers.begin());std::cout << "Reference count: " << buffer.use_count() << std::endl; // 1// 最后一个引用消失时自动释放
}
使用 std::vector<std::shared_ptr<SecureBuffer>> 统一管理多个 SecureBuffer:
- 可以观察 shared_ptr 的引用计数变化
- 确保对象在所有引用结束后自动释放
- 演示了共享指针的使用场景
测试要求(利用任务1的打印方法打印出内存内容):
- 使用 SafeDelete 测试
- 调用SecureBuffer类的修改方法(在任务1中已经实现),修改对象,之后进行移动构造测试移动语义
- 使用 std::unique_ptr 进行内存管理
- 使用 std::shared_ptr 进行共享引用管理
- 使用 std::vector 容器存储 shared_ptr
提交:
1. 代码(c++)
#include <iostream>
#include <memory>
#include <vector>
#include <cstring>// SafeDelete
template<typename T>
void SafeDelete(T*& ptr) {if (ptr != nullptr) {ptr->~T(); // 显式调用析构函数std::memset(ptr, 0, sizeof(T)); // 清空内存内容::operator delete(ptr); // 使用 operator delete 释放内存ptr = nullptr; // 置空指针}
}// SecureBuffer 类
class SecureBuffer {
public:SecureBuffer(size_t size) : size_(size), data_(new uint8_t[size]) {std::memset(data_, 0xCC, size_); // 初始化填充 0xCC}~SecureBuffer() {if (data_) {std::memset(data_, 0, size_); // 安全清理delete[] data_;data_ = nullptr;size_ = 0;}}// 禁用拷贝构造和拷贝赋值SecureBuffer(const SecureBuffer&) = delete;SecureBuffer& operator=(const SecureBuffer&) = delete;// 移动构造函数SecureBuffer(SecureBuffer&& other) noexcept : size_(other.size_), data_(other.data_) {other.size_ = 0;other.data_ = nullptr;}// 移动赋值运算符SecureBuffer& operator=(SecureBuffer&& other) noexcept {if (this != &other) {// 清理当前对象资源if (data_) {std::memset(data_, 0, size_);delete[] data_;}// 转移资源所有权size_ = other.size_;data_ = other.data_;// 置空源对象other.size_ = 0;other.data_ = nullptr;}return *this;}// 打印缓冲区内容(实验一中实现过)void print_data() const {for (size_t i = 0; i < size_; ++i) {std::cout << std::hex << (int)data_[i] << " ";}std::cout << std::endl;}// 修改缓冲区内容 // (实验一中memset(m_data,0xCC,m_size);这里写成一个方法)void modify_data(uint8_t value) {if (data_) {std::memset(data_, value, size_);}}size_t size() const { return size_; }private:size_t size_;uint8_t* data_;
};
2. 测试用例
// 测试用例
int main() {// 1. 测试 SafeDelete{std::cout << "=== Testing SafeDelete ===" << std::endl;SecureBuffer* buffer = new SecureBuffer(5);buffer->print_data(); // 输出初始值(0xCC)buffer->modify_data(0xFF);buffer->print_data(); // 输出修改后的值(0xFF)SafeDelete(buffer); // 安全删除std::cout << "After SafeDelete: " << (buffer == nullptr ? "Success" : "Failed") << std::endl;}// 2. 测试移动语义{std::cout << "\n=== Testing Move Semantics ===" << std::endl;SecureBuffer buffer1(5);buffer1.modify_data(0xAA);std::cout << "Buffer1 before move: ";buffer1.print_data();SecureBuffer buffer2 = std::move(buffer1); // 移动构造std::cout << "Buffer2 after move: ";buffer2.print_data();std::cout << "Buffer1 after move (should be empty): " << buffer1.size() << std::endl;}// 3. 测试 std::unique_ptr{std::cout << "\n=== Testing std::unique_ptr ===" << std::endl;std::unique_ptr<SecureBuffer> uniqueBuffer = std::make_unique<SecureBuffer>(3);uniqueBuffer->modify_data(0x11);uniqueBuffer->print_data();// unique_ptr 会自动释放内存}// 4. 测试 std::shared_ptr{std::cout << "\n=== Testing std::shared_ptr ===" << std::endl;std::shared_ptr<SecureBuffer> sharedBuffer1 = std::make_shared<SecureBuffer>(4);sharedBuffer1->modify_data(0x22);sharedBuffer1->print_data();std::shared_ptr<SecureBuffer> sharedBuffer2 = sharedBuffer1; // 共享所有权std::cout << "Use count: " << sharedBuffer2.use_count() << std::endl;}// 5. 测试 std::vector<std::shared_ptr<SecureBuffer>>{std::cout << "\n=== Testing std::vector<std::shared_ptr<SecureBuffer>> ===" << std::endl;std::vector<std::shared_ptr<SecureBuffer>> bufferVec;bufferVec.push_back(std::make_shared<SecureBuffer>(2));bufferVec.push_back(std::make_shared<SecureBuffer>(3));bufferVec.push_back(std::make_shared<SecureBuffer>(4));for (const auto& buf : bufferVec) {buf->print_data();}}return 0;
}
3. 过程及结果截图

in use at exit: 0 bytes:程序结束时所有动态分配的内存均被释放。18 allocs, 18 frees:内存分配和释放完全匹配,没有泄漏。ERROR SUMMARY: 0:没有非法内存访问、未初始化内存使用等问题。
4. 文字分析
要求:回顾和内存管理相关的3次实验内容,可以从这个角度进行总结:
手动管理内存(new/delete包括构造析构和分配释放)-> SafeDelete
拷贝构造 -> 移动构造
裸指针 -> 智能指针(unique_ptr、shared_ptr)
容器
手动管理容易导致内存泄漏、悬垂指针或敏感数据残留,而 SafeDelete 通过安全释放、内存清零和指针置空,提高了安全性。
深拷贝在涉及大对象时性能较差,而移动语义通过直接转移资源所有权,避免了不必要的复制,提升了效率,尤其适用于临时对象或智能指针(如 std::unique_ptr)。
裸指针需要手动管理生命周期,容易出错,而智能指针(std::unique_ptr 独占所有权、std::shared_ptr 共享所有权)结合容器(如 std::vector)可以自动管理动态对象的生命周期,减少内存泄漏风险,同时利用移动语义优化性能。
