从shared_ptr泄漏测试代码中得到的结果

时间:2017-10-19 13:53:40

标签: c++ memory-leaks shared-ptr smart-pointers

我期望test1.cpp和test2.cpp发出类似的结果 每次运行都打印相同,因为没有内存泄漏。
但事实并非如此。我不知道为什么。
你能不能让我知道它是如何理解这种情况的。

test1.cpp

#include <iostream>
#include <memory>
using namespace std;

class Class {
public:
    shared_ptr<int> value1;
    shared_ptr<int> value2;
    Class() {};
};

int main() {
    char pause;
    while (true) {
        shared_ptr<Class>cls(new Class());
        cout << cls.get() << endl;
        cin >> pause;
    }
    return 0;
}

我的结果

0x94b5a10
1
0x94b5a28
1
0x94b5a10
1
0x94b5a28
1
0x94b5a10

测试2.cpp

#include <iostream>
#include <memory>
using namespace std;

class Class {
public:
    int value1;
    int value2;
    Class() {};
};

int main() {
    char pause;
    while (true) {
        shared_ptr<Class>cls(new Class());
        cout << cls.get() << endl;
        cin >> pause;
    }
    return 0;
}

我的结果

0x91baa10
1
0x91baa10
1
0x91baa10
1
0x91baa10
1
0x91baa10

test3.cpp - 这是最令人满意的结果..

#include <iostream>
#include <memory>
using namespace std;

class Class {
public:
    shared_ptr<int> value1;
    shared_ptr<int> value2;
    shared_ptr<int> value3;
    Class() {};
};

int main() {
    char pause;
    while (true) {
        shared_ptr<Class>cls(new Class());
        cout << cls.get() << endl;
        cin >> pause;
    }
    return 0;
}

我的结果

0x826ba10
1
0x826ba10
1
0x826ba10
1
0x826ba10
1
0x826ba10

3 个答案:

答案 0 :(得分:2)

您要打印的是Class(错误名称)对象的地址。

在第二种情况下,当shared_ptr超出范围并且在同一内存位置分配新对象时,将释放Class对象。哪个好。

在第一种情况下,由于某种原因,为新的Class对象选择了不同的地址。根据经验,它必须与所做的其他分配和解除分配有关。如果不看分配器的内部逻辑,你就不会得到比这更精确的答案。

而且,无论如何,你绝对不应该依赖任何类型逻辑之后的地址。你应该根本不在乎。

答案 1 :(得分:0)

在每个循环中,创建一个新的局部变量 shared_ptrcls,并为该对象的内存分配动态。当一个循环结束时,旧对象自动删除,然后新循环将创建一个新对象,并且它不必具有与上一循环中旧对象相同的地址,因为它是全新的。两种结果都是正常的,两种情况都可能发生。

答案 2 :(得分:0)

问题解决了。我期望的是,在while循环结束时将删除每个本地对象(在这种情况下,测试函数结束时为test4.cpp)。但事实并非如此。

test4.cpp

#include <iostream>
#include <memory>
using namespace std;

class Class {
public:
    shared_ptr<int> value1;
    shared_ptr<int> value2;
    Class() {};
};

char test() {
  char pause;
  shared_ptr<Class>cls(new Class());
  cout << cls.get() << endl;
  cin >> pause;
  return pause;
}

int main() {
    while (true) {
      if ('q' == test()) break;
    }
    return 0;
}

测试结果

root@real:~# ltrace -C ./test
__libc_start_main(0x8048d2f, 1, 0xffffd4c4, 0x8048fc0 <unfinished ...>
std::ios_base::Init::Init()(0x804b1d9, 0x4a00, 0xf7c81dc8, 0xf7ffb000) = 0xf7fbde14
__cxa_atexit(0x8048920, 0x804b1d9, 0x804b05c, 0xf7ffb000)    = 0
operator new(unsigned int)(16, 0xffffd4c4, 0xf7fb608c, 0x8048d69) = 0x8050a10
operator new(unsigned int)(16, 0xffffd4c4, 0xf7fb608c, 0x8048d69) = 0x8050a28
std::ostream& std::ostream::_M_insert<void const*>(void const*)(0x804b120, 0x8050a10, 0xf7fb608c, 0x8048d69) = 0x804b120
std::ostream::put(char)(0x804b120, 10, 0xf7fb608c, 0x8048d690x8050a10
) = 0x804b120
std::ostream::flush()(0x804b120, 10, 0xf7fb608c, 0x8048d69)  = 0x804b120
std::basic_istream<char, std::char_traits<char> >& std::operator>><char, std::char_traits<char> >(std::basic_istream<char, std::char_traits<char> >&, char&)(0x804b060, 0xffffd3f3, 0xf7fb608c, 0x8048d691
) = 0x804b060
operator delete(void*, unsigned int)(0x8050a10, 16, 0xf7f26f0b, 0xf7fbd660) = 0
operator delete(void*, unsigned int)(0x8050a28, 16, 0xf7f26f0b, 0xf7fbd660) = 0x8050a08
operator new(unsigned int)(16, 0xffffd3f3, 0xf7fb608c, 0x8048d69) = 0x8050a28
operator new(unsigned int)(16, 0xffffd3f3, 0xf7fb608c, 0x8048d69) = 0x8050a10
std::ostream& std::ostream::_M_insert<void const*>(void const*)(0x804b120, 0x8050a28, 0xf7fb608c, 0x8048d69) = 0x804b120
std::ostream::put(char)(0x804b120, 10, 0xf7fb608c, 0x8048d690x8050a28
) = 0x804b120
std::ostream::flush()(0x804b120, 10, 0xf7fb608c, 0x8048d69)  = 0x804b120
std::basic_istream<char, std::char_traits<char> >& std::operator>><char, std::char_traits<char> >(std::basic_istream<char, std::char_traits<char> >&, char&)(0x804b060, 0xffffd3f3, 0xf7fb608c, 0x8048d69q
) = 0x804b060
operator delete(void*, unsigned int)(0x8050a28, 16, 0xf7f26f0b, 0xf7fbd660) = 0
operator delete(void*, unsigned int)(0x8050a10, 16, 0xf7f26f0b, 0xf7fbd660) = 0x8050a20
std::ios_base::Init::~Init()(0x804b1d9, 0, 0, 0xf7ca38d7)    = 0xf7fbc5c0
+++ exited (status 0) +++