1 内存泄漏:动态分配的内存没有被正确释放,导致程序持续占用内存直至结束运行。
Example:
void memoryLeakExample() {int* ptr = new int(5); // 分配了一个int类型的内存// 这里没有调用delete来释放内存
}
solution:
自己delete或者使用智能指针
智能指针内存泄露的情况:
假设我们有两个类A和B,它们相互引用对方的实例,使用std::shared_ptr进行管理。这种情况下,如果不加以处理,就会导致循环引用和内存泄漏。
#include <memory>class B; // 前置声明class A {
public:std::shared_ptr<B> bPtr;// ...
};class B {
public:std::shared_ptr<A> aPtr;// ...
};int main() {std::shared_ptr<A> a = std::make_shared<A>();std::shared_ptr<B> b = std::make_shared<B>();a->bPtr = b;b->aPtr = a;// 此时a和b相互引用,会导致循环引用和内存泄漏return 0;
}
solution:
为了解决这个问题,我们可以使用std::weak_ptr来打破循环引用:
#include <memory>class B; // 前置声明class A {
public:std::shared_ptr<B> bPtr;// ...
};class B {
public:std::weak_ptr<A> aWeakPtr; // 使用weak_ptr来打破循环引用// ...
};int main() {std::shared_ptr<A> a = std::make_shared<A>();std::shared_ptr<B> b = std::make_shared<B>();a->bPtr = b;b->aWeakPtr = a; // 使用weak_ptr// 现在循环引用被打破,不会导致内存泄漏return 0;
}
通过将B类中的aPtr改为std::weak_ptr,我们成功打破了循环引用,避免了内存泄漏问题
2 二次释放:尝试释放已经被释放的内存,可能导致程序崩溃。
Example:
int main() {int* ptr = new int(5); // 分配了一个int类型的内存delete ptr; // 释放内存delete ptr; // 尝试再次释放同一块内存,这是错误的return 0;
}
solution:
我们需要确保在释放内存后将指针置为nullptr,这样可以避免尝试释放已经被释放的内存。另外,使用智能指针(如std::unique_ptr)
3 悬空指针:指针指向的内存已经被释放,将指针置为nullptr,导致潜在的错误访问。
int* ptr = new int(5); // 分配了一个int类型的内存
delete ptr; // 释放内存
ptr = nullptr; // 将指针置为空指针
// 在之后的代码中,错误地使用了已经被释放的指针
int value = *ptr; // 这里访问了一个已经被释放的内存
solution:
多做if (ptr != nullptr)判断
4 内存越界访问:访问超出动态分配内存范围的内存,可能导致未定义行为。
int* arr = new int[5]; // 分配了包含5个int的内存块// 尝试访问超出分配内存范围的内存
arr[5] = 10; // 这里访问了arr数组中超出范围的内存delete[] arr; // 释放内存
solution:
我们需要确保在访问动态分配的内存时不要超出其范围。另外,可以使用标准库提供的容器类(
如std::vector)来代替手动管理动态数组,这样可以避免手动管理内存时可能出现的问题。
5 不正确的所有权管理:多个指针指向同一块动态分配的内存,但没有正确管理所有权,可能导致资源释放错误或重复释放。
int* ptr1 = new int(5); // 分配了一个int类型的内存
int* ptr2 = ptr1; // ptr2指向了ptr1所指向的内存delete ptr1; // 释放内存// 错误地尝试使用已经被释放的内存
*ptr2 = 10; // 这里访问了已经被释放的内存
solution:
使用智能指针或者使用std::move转移所有权
6 竞争条件:多个线程同时访问和修改动态分配的内存,可能导致数据不一致或者意外的行为。
#include <iostream>
#include <thread>int x = 0;void incrementX() {for (int i = 0; i < 1000000; ++i) {x++; // 读取x的值,加一,然后写回x}
}int main() {std::thread t1(incrementX);std::thread t2(incrementX);t1.join();t2.join();std::cout << "The value of x is: " << x << std::endl;return 0;
}
solution:
使用锁啊std::mutex
7 内存破坏:多个线程同时访问和修改同一块内存,可能导致内存破坏和数据损坏。
#include <iostream>int main() {int* ptr = new int(5); // 分配了一个int类型的内存int* invalidPtr = ptr + 1; // 错误地访问了ptr指针之后的内存*invalidPtr = 10; // 错误地修改了无效指针指向的内存delete ptr; // 释放内存return 0;
}