shared_ptr과 포인터 변환에 대한 질문2
글쓴이: telepathy070 / 작성시간: 화, 2016/01/05 - 6:06오후
class StringContainer
{
public:
StringContainer();
char tmp_array[32];
};
StringContainer::StringContainer()
{
memset(tmp_array, 0, sizeof(tmp_array));
strcpy(tmp_array, "dream comes true!!!");
}
long long extern_raw_cstring_address;
std::shared_ptr<StringContainer> ext_cr;
function A()
{
std::shared_ptr<StringContainer> cr = shared_ptr<StringContainer>(new StringContainer());
extern_raw_cstring_address = (long long)(reinterpret_cast<void * >(&cr)); //shared_ptr 주소 출력
ext_cr = cr; //외부 변수에 대입하여 shared_ptr 함수를 벗어나도 삭제되지 않게 막기
}
function B()
{
StringContainer* ext_data = ext_cr.get();
TRACE(ext_data->tmp_array); //정상적으로 출력됨
TRACE("\r\n");
std::shared_ptr<StringContainer> * test_cstring = reinterpret_cast<shared_ptr<StringContainer> * >(extern_raw_cstring_address); //캐스팅된 변수가 이상함1
StringContainer* recover_raw_cstring = ( * test_cstring).get(); //내부 데이터 역시 깨져있음2
TRACE((*recover_raw_cstring).tmp_array); //여기서 종료됨3
TRACE("\r\n");
}일단 제가 하려는게 다음과 같은겁니다.
함수 A()에서 shared_ptr를 만들고 그 주소를 저장합니다.
함수 B()에서 그 주소를 가지고 shared_ptr를 다시 가져옵니다.
하지만 함수B에서 실제 주소인 extern_raw_cstring_address를 가지고 shared_ptr를 다시 불러오면 데이터가깨져있어요
함수 A()벗어났을때 shared_ptr이 삭제된건 절대아니구요 (왜냐하면 deleter함수를 등록해서 확인해보면 확실히 ext_cr때문에 삭제 안시켜요)
왜 shared_ptr를 정상적으로 메모리에서 가져오지 못할까요?
함수B()를 함수 A() 끝나기 전에 불러도 정상적으로 출력이 되는데...함수 A()가 종료된뒤 함수 B()를 부르면 에러로 종료됩니다.
Forums:


shared_ptr은 내부의 pointer를 공유하는
shared_ptr은 내부의 pointer를 공유하는 그냥 객체입니다.
함수 A 종료시점에 cr과 ext_cr이 가지고 있는 내부 pointer는 유효하지만 cr은 종료되어버리므로,
그 cr의 pointer를 가지고 있는 extern_raw_cstring_address는 유효하지 않은 cr의 pointer를 가지고 있게 됩니다.
정말 그렇더라구요.. 그래서 shared_ptr를
정말 그렇더라구요..
그래서 shared_ptr를 클래스 넣어서 관리하는 것으로 변경하고 있습니다.
shared_ptr 과 new 사용방법
테스트해봤습니다.
http://en.cppreference.com/w/cpp/memory/shared_ptr
http://blog.naver.com/lobo_prix/220421546490
shared_ptr 을 전역변수로 사용하더라도. main함수가 return 될때.
소멸자가 자동으로 호출됩니다. delete p; 를 하지 않아도 되는 경우가 있습니다.
shared_ptr 을 지역변수로 사용하면. 함수가 return 될때. 소멸자가 함께 호출됩니다.
shared_ptr 은 같은 주소를 함께 참조하면 오류가 발생합니다.
---------------------------------------------
TRACE() 는 255 자를 넘을 경우. 주의해야 합니다.
사용방법은 printf() 와 같은 방식입니다.
TRACE 매크로
https://msdn.microsoft.com/ko-kr/library/4wyz8787%28v=vs.90%29.aspx
https://msdn.microsoft.com/en-us/library/6w95a4ha.aspx
---------------------------------------------
char buf[1024];
sprintf(buf, "%s", "test");
OutputDebugString(buf); 도 사용하실 수 있습니다.
---------------------------------------------
윈도우에서 콘솔화면을 띄워서. printf()를 사용할 수 있습니다.
AllocConsole();
freopen("CONOUT$", "wt", stdout);
콘솔 윈도우 닫기
FreeConsole();
#include <iostream> #include <memory.h> #include <stdio.h> #include <string.h> #include <atomic> #include <memory> #include <thread> #include <chrono> #include <mutex> #include <functional> using namespace std; class StringContainer { public: StringContainer(); virtual ~StringContainer() { printf("~StringContainer() 소멸자 : %x : %s\n", this, m_myname.c_str()); } string m_myname; char tmp_array[32]; }; StringContainer::StringContainer() { printf("StringContainer() 생성자 : %x : %s\n", this, m_myname.c_str()); printf("this : %x\n", this); printf("tmp_array : %x\n", tmp_array); memset(tmp_array, 0, sizeof(tmp_array)); strcpy(tmp_array, "dream comes true!!!"); } long long extern_raw_cstring_address; std::shared_ptr<StringContainer> ext_cr; //function A() void A() { printf("---------------------------------------------------------A()\n"); StringContainer * p = new StringContainer(); p->m_myname = "A()"; #if 0 포인터를 공유하는 방법?? std::shared_ptr<StringContainer>* p = (shared_ptr<StringContainer>*)new StringContainer(); shared_ptr<StringContainer> sp2 = shared_ptr<StringContainer>(p); shared_ptr<StringContainer> sp1(p); #endif //shared_ptr 을 지역변수로 사용하면. 함수가 return 될때. 소멸자가 함께 호출됩니다. //shared_ptr 은 같은 주소를 함께 참조하면 오류가 발생합니다. shared_ptr<StringContainer> sp1(p); extern_raw_cstring_address = (long long)p; printf("A() p : %x\n", p ); printf("A() p->tmp_array : %x\n", p->tmp_array); printf("A() p->tmp_array : %s\n", p->tmp_array); printf("_msize : %d\n", _msize(p) ); } //function B() void B() { printf("---------------------------------------------B()\n"); std::shared_ptr<StringContainer> * test_cstring = reinterpret_cast<shared_ptr<StringContainer> * >(extern_raw_cstring_address); //캐스팅된 변수가 이상함1 StringContainer * p = (StringContainer*) test_cstring; printf("BB() p : %x\n", p); printf("BB() p->tmp_array : %s\n", p->tmp_array); printf("_msize : %d\n", _msize(p)); } void A2() { printf("---------------------------------------------------------A2()\n"); StringContainer * p = new StringContainer(); p->m_myname = "A2()"; ext_cr = shared_ptr<StringContainer>(p); printf("A2() p->tmp_array : %x\n", p->tmp_array); printf("A2() p->tmp_array : %s\n", p->tmp_array); printf("_msize : %d\n", _msize(p)); } void B2() { printf("---------------------------------------------B2()\n"); StringContainer * p = ext_cr.get(); printf("B2() p->tmp_array : %x\n", p->tmp_array); printf("B2() p->tmp_array : %s\n", p->tmp_array); printf("_msize : %d\n", _msize(p)); //shared_ptr 을 전역변수로 사용하더라도. main함수가 return 될때. //소멸자가 자동으로 호출됩니다. delete p; 를 하지 않아도 되는 경우가 있습니다. } int n; void AA() { printf("---------------------------------------------------------AA()\n"); StringContainer * p = new StringContainer(); p->m_myname = "AA()"; n = (int)p; printf("AA() p : %x\n", p); printf("AA() p : %s\n", p->tmp_array); printf("_msize : %d\n", _msize(p)); } void BB() { printf("---------------------------------------------BB()\n"); StringContainer * p = (StringContainer*)n; printf("BB() p : %x\n", p); printf("BB() p : %s\n", p->tmp_array); printf("_msize : %d\n", _msize(p)); delete p; } void F1() { printf("---------------------------------------------------------F1()\n"); char * p = new char[100]; strcpy(p, "test"); n = (int)p; printf("F1() p : %x\n", p); printf("F1() p : %s\n", p); printf("_msize : %d\n", _msize(p)); } void F2() { printf("---------------------------------------------F2()\n"); char * p = (char*)n; printf("F2() p : %x\n", p); printf("F2() p : %s\n", p); printf("_msize : %d\n", _msize(p)); delete [] p; } int main(int argc, char** argv) { A(); B(); A2(); B2(); AA(); BB(); F1(); F2(); printf("main end\n"); return 0; } 출력 결과 ---------------------------------------------------------A() StringContainer() 생성자 : 3d3f08 : this : 3d3f08 tmp_array : 3d3f10 A() p : 3d3f08 A() p->tmp_array : 3d3f10 A() p->tmp_array : dream comes true!!! _msize : 40 ~StringContainer() 소멸자 : 3d3f08 : A() ---------------------------------------------B() BB() p : 3d3f08 BB() p->tmp_array : dream comes true!!! _msize : 40 ---------------------------------------------------------A2() StringContainer() 생성자 : 3d3f08 : this : 3d3f08 tmp_array : 3d3f10 A2() p->tmp_array : 3d3f10 A2() p->tmp_array : dream comes true!!! _msize : 40 ---------------------------------------------B2() B2() p->tmp_array : 3d3f10 B2() p->tmp_array : dream comes true!!! _msize : 40 ---------------------------------------------------------AA() StringContainer() 생성자 : 3d3f58 : this : 3d3f58 tmp_array : 3d3f60 AA() p : 3d3f58 AA() p : dream comes true!!! _msize : 40 ---------------------------------------------BB() BB() p : 3d3f58 BB() p : dream comes true!!! _msize : 40 ~StringContainer() 소멸자 : 3d3f58 : AA() ---------------------------------------------------------F1() F1() p : 3d3fa8 F1() p : test _msize : 100 ---------------------------------------------F2() F2() p : 3d3fa8 F2() p : test _msize : 100 main end ~StringContainer() 소멸자 : 3d3f08 : A2() -------------------------------- Process exited after 0.4688 seconds with return value 0 계속하려면 아무 키나 누르십시오 . . .----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
그렇지 않아도 2번째 링크에서 지적한 문제가 저한테도
그렇지 않아도 2번째 링크에서 지적한 문제가 저한테도 발생해서
http://blog.naver.com/lobo_prix/220421546490
좀더 shared_ptr에 대해서 공부해봐야겠네요
테스트 감사해요
댓글 달기