使用shared_ptr时内存泄漏

问题描述 投票:0回答:1

我一直在努力解决一个涉及城市各地区用水减少的问题。该程序需要输入地区编号和餐厅所在地区的编号。这个想法是让该餐厅成为按减少顺序排列的最后一个(类似于约瑟夫问题,如果我没记错的话)。这是我使用智能指针编写的代码:

#include <iostream>
#include <stdexcept>
#include <vector>
#include <memory>

using namespace std;

struct District {
    int district_number;
    shared_ptr<District> next;
};

vector<int> Reduction(int N, int M) {
    vector<int> reduction_order;

    auto start = make_shared<District>();
    start->district_number = 1;
    auto previous = start;

    for (int i = 2; i <= N; i++) {
        auto new_district = make_shared<District>();
        new_district->district_number = i;
        previous->next = new_district;
        previous = previous->next;
    }
    previous->next = start;

    int counter = 0;
    auto current = previous->next;

    while (current != current->next) {
        if (counter % M == 0) {
            reduction_order.push_back(current->district_number);
            auto temp = current->next;
            previous->next = temp;
            current = nullptr;
            current = previous->next;
        } else {
            previous = current;
            current = current->next;
        }
        
        counter++;
    }
    reduction_order.push_back(current->district_number);
    current = nullptr;

    return reduction_order;
}

int StepSelection(int N, int K) {
    if (N <= 0 || K <= 0 || K > N)
        throw domain_error("The number of districts and the ordinal number of the district are positive integers and the ordinal number of the district cannot be greater than the number of districts.");
    if (N != 1 && K == 1)
        return 0;
    int M(1);

    vector<int> reduction_order(Reduction(N, M));

    while (reduction_order[reduction_order.size() - 1] != K) {
        M++;
        reduction_order = Reduction(N, M);
        if (M >= 5 * N) {
            M = 0;
            break;
        }
    }

    return M;
}

int main() {
    try {
        int N, K;
        cout << "Enter the number of districts in the city: ";
        cin >> N;
        cout << "Enter the ordinal number of the district where the restaurant is located: ";
        cin >> K;
        cout << "Required step: " << StepSelection(N, K);
    }
    catch (domain_error& d) {
        cout << d.what();
    }

    return 0;
}

这是一个示例输出:

Enter the number of districts in the city: 10
Enter the ordinal number of the district where the restaurant is located: 4
Required step: 2

这是正确的输出,因此看起来代码运行良好并且完成了工作。但也存在一些内存泄漏,具体来说,根据 LeakSanitizer,2 次分配中泄漏了 80 个字节。这是消息:

==1453486==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 40 byte(s) in 1 object(s) allocated from:
#0 0x7f2ecb337587 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cc:104
#1 0x55c4ecd58b96 in __gnu_cxx::new_allocator, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x55c4ecd587ac in std::allocator_traits, (__gnu_cxx::_Lock_policy)2> > >::allocate(std::allocator, (__gnu_cxx::_Lock_policy)2> >&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:443
#3 0x55c4ecd58179 in std::__allocated_ptr, (__gnu_cxx::_Lock_policy)2> > > std::__allocate_guarded, (__gnu_cxx::_Lock_policy)2> > >(std::allocator, (__gnu_cxx::_Lock_policy)2> >&) /usr/include/c++/9/bits/allocated_ptr.h:97
#4 0x55c4ecd57ade in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count>(District*&, std::_Sp_alloc_shared_tag >) /usr/include/c++/9/bits/shared_ptr_base.h:677
#5 0x55c4ecd5718c in std::__shared_ptr::__shared_ptr>(std::_Sp_alloc_shared_tag >) /usr/include/c++/9/bits/shared_ptr_base.h:1344
#6 0x55c4ecd56463 in std::shared_ptr::shared_ptr>(std::_Sp_alloc_shared_tag >) /usr/include/c++/9/bits/shared_ptr.h:359
#7 0x55c4ecd5543f in std::shared_ptr std::allocate_shared>(std::allocator const&) /usr/include/c++/9/bits/shared_ptr.h:702
#8 0x55c4ecd54c8f in std::shared_ptr std::make_shared() /usr/include/c++/9/bits/shared_ptr.h:718
#9 0x55c4ecd5381e in Reduction(int, int) main.cpp:28
#10 0x55c4ecd53fc0 in StepSelection(int, int) main.cpp:70
#11 0x55c4ecd54287 in _main() main.cpp:87
#12 0x55c4ecd54415 in main main.cpp:101
#13 0x7f2ecad0e082 in __libc_start_main ../csu/libc-start.c:308

Direct leak of 40 byte(s) in 1 object(s) allocated from:
#0 0x7f2ecb337587 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cc:104
#1 0x55c4ecd58b96 in __gnu_cxx::new_allocator, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x55c4ecd587ac in std::allocator_traits, (__gnu_cxx::_Lock_policy)2> > >::allocate(std::allocator, (__gnu_cxx::_Lock_policy)2> >&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:443
#3 0x55c4ecd58179 in std::__allocated_ptr, (__gnu_cxx::_Lock_policy)2> > > std::__allocate_guarded, (__gnu_cxx::_Lock_policy)2> > >(std::allocator, (__gnu_cxx::_Lock_policy)2> >&) /usr/include/c++/9/bits/allocated_ptr.h:97
#4 0x55c4ecd57ade in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count>(District*&, std::_Sp_alloc_shared_tag >) /usr/include/c++/9/bits/shared_ptr_base.h:677
#5 0x55c4ecd5718c in std::__shared_ptr::__shared_ptr>(std::_Sp_alloc_shared_tag >) /usr/include/c++/9/bits/shared_ptr_base.h:1344
#6 0x55c4ecd56463 in std::shared_ptr::shared_ptr>(std::_Sp_alloc_shared_tag >) /usr/include/c++/9/bits/shared_ptr.h:359
#7 0x55c4ecd5543f in std::shared_ptr std::allocate_shared>(std::allocator const&) /usr/include/c++/9/bits/shared_ptr.h:702
#8 0x55c4ecd54c8f in std::shared_ptr std::make_shared() /usr/include/c++/9/bits/shared_ptr.h:718
#9 0x55c4ecd5381e in Reduction(int, int) main.cpp:28
#10 0x55c4ecd53eb2 in StepSelection(int, int) main.cpp:66
#11 0x55c4ecd54287 in _main() main.cpp:87
#12 0x55c4ecd54415 in main main.cpp:101
#13 0x7f2ecad0e082 in __libc_start_main ../csu/libc-start.c:308

SUMMARY: AddressSanitizer: 80 byte(s) leaked in 2 allocation(s).

有什么想法可能导致此问题以及如何解决此问题吗?

c++ pointers memory-leaks
1个回答
0
投票
current = nullptr;

不会对

current
指向的对象执行任何操作,它只是将指针与其分离。

Reduction
循环结束时,您会得到
current->next = current

通过重置
current->next
来打破这里的循环:

current->next = nullptr;

current->next.reset();
© www.soinside.com 2019 - 2024. All rights reserved.