boost 스마트 포인터 사용시 메모리 할당 해제 문제

dorado2의 이미지


typedef struct _a         
{
  unsigned char a,b;
} a;

typedef struct _b
{
  unsigned char c;
  unsigned char* d;
} b;


class pkt_buff
{
  pkt_buff(unsigned char* data, int len);
~pkt_buff();
private:   
   a   m_a;
    b   m_b;
}

pkt_buff::pkt_buff(unsigned char* data, int len)
{
    memcpy(&m_a, data, 2);   

    m_b.c = *(data+2);

     m_b.d = new unsigned char[len-3];
    memcpy(m_b.d, data+3, len-3);

     ...
}

pkt_buff::~pkt_buff()
{
     delete m_b.d;
}

typedef boost::shared_ptr<pkt_buff> pkb_ptr;
typedef std::vector<pkb_ptr> pkb_list;

뭐 대충 위와 같은 식으로 짰는데요.
시리얼로 들어오는 패킷을 레이어별 헤더로 구분하고,
특정 데이터를 저장하는 부분이 필요해서요.

일종의 패킷 스니퍼를 작성하고 있습니다. 패킷 하나의 양은 1-200byte로 크지 않습니다. 그리고 들어오는 속도도 그리 빠르지는 않습니다 .

패킷 하나가 시리얼로 들어오면 (char array 형태로 통짜로 들어옵니다.) 위 pkt_buff 클래스를 이용해서 pkt_buff 객체를 하나 만들고, vector에 저장합니다.

들어오는 패킷을 vector에 쭈욱 저장하고, 화면에서는 자료구조에 담긴 패킷들을 하나하나 뽑아내서 화면에 패킷을 표시하는 프로그램입니다.

vector에 저장할 때, 자료형을 그대로 담는 건 메모리 오버해드가 크다고 해서 저렇게 포인터만 저장하는 걸로 알고 있습니다.

그런데 boost의 스마트 포인터는 scope를 벗어나면 자기가 메모리 해제를 하는 것으로 알고 있는데, 파괴자 ~pkt_buff() 부분도 수행을 하는 것입니까? 아니면 자기가 알아서 해주는 것인가요?

위에서 m_b.d 부분은 new로 할당을 해줘야 하는 부분이라서...

그리고, 위같은 구조로 사용해도 무방할까요?

더 효율적인 구조는 없을지 문의드립니다.

lovemyin의 이미지

스마트 포인터의 용도는 무지 많지만...
예를 들어 예외가 발생할 부분을 스마트 포인터를 써서 간단하게 대체할 수 있다든지...

어쨋든 스마트 포인터는 힙에 할당된 메모리를 생성자로 넘겨줌으로써 포인터를 객체처럼 동작하게 합니다.
당연히 객체이기 때문에 scope를 벗어나면 메모리가 해제됩니다.
소멸자에 의해...

/***************************************************
* 가장 심플한 것이 가장 아름다운 것이다.
***************************************************/

doldori의 이미지

별 문제는 없어 보입니다만...

dorado2 wrote:
vector에 저장할 때, 자료형을 그대로 담는 건 메모리 오버해드가 크다고 해서 저렇게 포인터만 저장하는 걸로 알고 있습니다.

어차피 그 자료는 어딘가에 저장해야 하므로 vector에 담는다고 해서 오버헤드가
크게 달라지지는 않습니다. 다만 그 자료가 복사될 때는 얘기가 다르지요. 복사본
두 벌을 가지고 있느냐, 아니면 하나만 저장해놓고 포인터로 같은 자료를 참조하느냐의
차이입니다. pkt_buff 개체의 복사가 빈번하지 않다면 그냥 vector<pkt_buff>를
쓰는 것이 간단합니다.

dorado2 wrote:
그런데 boost의 스마트 포인터는 scope를 벗어나면 자기가 메모리 해제를 하는 것으로 알고 있는데, 파괴자 ~pkt_buff() 부분도 수행을 하는 것입니까? 아니면 자기가 알아서 해주는 것인가요?

그 말이 그 말 같은데... ^^; 물론 ~pkt_buff()도 수행됩니다. ~shared_ptr()이
내부에서 해주죠. 따라서 프로그래머가 직접 delete 할 필요는 없습니다.

dorado2 wrote:
pkt_buff::~pkt_buff()
{
     delete m_b.d;
}

~pkt_buff()에서 delete가 아니라 delete[]를 써야 합니다.
doldori의 이미지

생각해보니 unsigned char* 대신에 basic_string<unsigned char>를 쓰면
~pkt_buff()도 필요없겠습니다. 복사/대입도 저절로 해결되고요.

typedef struct _b
{
  unsigned char c;
  basic_string<unsigned char> d;
} b;

pkt_buff::pkt_buff(unsigned char* data, int len)
{
    memcpy(&m_a, data, 2);   

    m_b.c = *(data+2);

     m_b.d.assign(data+3, len-3);

     ...
}
dorado2의 이미지

답변 감사드립니다.

basic_string<unsigned char>에 대해서 찾아봐야 겠군요.
assign은 알겠는데, ~basic_string() 에서 다 delete되나 보군요.

boost 스마트 포인터를 쓰지 않고 vector<pkt_buff> 를 사용하는 경우에도 메모리 해제가 보장되나요?

그리고 사용하다 보면 선언만 하고 assign하지 않을 경우도 생길것 같은데, emtpy()나 capacity() 함수를 통해 그 여부를 알 수 있겠죠?

doldori의 이미지

dorado2 wrote:
basic_string<unsigned char>에 대해서 찾아봐야 겠군요.
assign은 알겠는데, ~basic_string() 에서 다 delete되나 보군요.

string이 basic_string<char>을 typedef한 것은 알고 계시겠지요.
basic_string<unsigned char> 역시 똑같은 방법으로 쓰면 됩니다.

dorado2 wrote:
boost 스마트 포인터를 쓰지 않고 vector<pkt_buff> 를 사용하는 경우에도 메모리 해제가 보장되나요?

네. vector가 소멸될 때 각 원소들의 소멸자를 먼저 호출합니다.

dorado2 wrote:
그리고 사용하다 보면 선언만 하고 assign하지 않을 경우도 생길것 같은데, emtpy()나 capacity() 함수를 통해 그 여부를 알 수 있겠죠?

empty()는 됩니다만 capacity()는 안 됩니다. 빈 스트링이라도 미리 메모리를
할당해놓는 구현도 가능한데 이때는 empty() == true 이지만 capacity() != 0 이지요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.