[완료]C++에서 객체 소멸후 멤버변수 값에 대해 궁금증이 있습니다.

lsfeel0204의 이미지

#include <iostream>
using namespace std;
 
class AAA
{
public:
        int a;
public:
	AAA()
	{
		cout<<"empty object"<<endl;
                a = 100;
                ShowYourName();
	}
	void ShowYourName()
	{
		cout<<"I'm class AAA"<<endl;
                cout<<a<<endl;
                a++;
	}
};
 
int main(void)
{
	AAA *obj1 = new AAA;
        obj1->ShowYourName();
 
        delete obj1;
        obj1->ShowYourName();
	return 0;
}
 
출력결과:
empty object
I'm class AAA
100
I'm class AAA
101
I'm class AAA
0  //  <--- ?????

위에서 보시다시피, AAA class를 obj1라는 이름으로 객체를 동적할당하고,
delete로 소멸시킨다음에, 소멸된 객체의 멤버함수를 호출했는데요.

일단 소멸된 객체의 멤버함수는 obj1 객체가 메모리 반환만 됬다 뿐이지, obj1이 해당 객체의 주소값을 담고 있기 때문에
멤버함수는 호출된다는 것 까지는 알겠는데요. 왜 멤버변수 a가 0으로 초기화되는지 모르겠습니다.

부디 알려주시면 감사하겠습니다!

klyx의 이미지

그냥 어쩌다 그렇게 된거라고 생각하세요.
몇번이고 해봐도 같은 결과가 나온다고해도, 그냥 우연이라고 생각하세요.
컴파일러의 디버깅 옵션등에서 자동으로 초기화해버릴수도 있지만, 표준에서는 애시당초 그러한 상황에 대해서는 '정의되지 않은 동작'을 하게되어있기 때문에 어떤 결과가 나올것이라고 예측해서 그걸 이용하는것 자체가 넌센스입니다.
할당되지 않은 객체의 멤버함수를 호출하는 시점에서 이미 잘못된 것입니다.

lsfeel0204의 이미지

delete이후의 변수 접근은 undefined behavior라고는 하는데..

gdb로 확인해 봤는데, delete하는 시점에서 멤버변수가 0값으로 초기화 되는 군요..

신기하네요ㅎㅎ;;

답변 감사드립니다.

익명 사용자의 이미지

일단 소멸된 객체의 멤버함수는 obj1 객체가 메모리 반환만 됬다 뿐이지, obj1이 해당 객체의 주소값을 담고 있기 때문에
멤버함수는 호출되는 것이 아닙니다.

AAA *obj = NULL;
obj->ShowYourName();

하면 깜짝 놀랄겁니다.

익명 사용자의 이미지

obj가 NULL값일 경우는 당연히 안되는 것이겠지만,

obj에 AAA 클래스 객체가 동적 할당된 뒤에, delete로 소멸시키더라도
obj가 해당 객체의 주소값을 가지고 있기 때문에, 멤버함수는 호출이 됩니다.

즉,

AAA *obj = NULL;
obj->ShowYourName();

는 당연히 안되는 게 맞고,

AAA *obj = new AAA;
delete obj;
obj->ShowYourName();

는 됩니다. 물론 이렇게 하면 안되는 것이 겠지요..
익명 사용자의 이미지

그런 생각으로 한번 직접 돌려보세요.
깜짝 놀랄겁니다. ^^

lsfeel0204의 이미지

해보니까...신기하게도 메세지는 출력되는데, 멤버변수에 접근할 때 segmentation fault가 발생되네요.

혹시 왜 그런지 알려주실 수 있으신지요?

code seg에는 접근 가능한데, heap에는 접근이 불가능해서 그런건가요?

(그리고 ShowYourName 멤버함수에 local 변수 선언 및 값 대입, 그리고 출력도 해보았는데 정상적으로 되네요.
즉, stack도 사용하고 정상동작도 다 되는데, 멤버변수에 접근만 하면 seg fault가 발생합니다.)

혹시 속시원하게 말씀해 주실분 계신지요 ㅠㅠ

DarkSide의 이미지

객체의 포인터가 null 이라도 어째튼 함수는 형성되고, obj->ShowYourName() 이 함수의 주소를 나타내게 되죠.

ifree의 이미지

obj->ShowYourName() 은 ShowYourName(this) 와 마찬가지이므로 돌아갈 수는 있을 듯.

lsfeel0204의 이미지

결국, 객체가 생성되지 않더라도...심지어 객체 포인터가 null값이더라도,

멤버 함수로 해당 class의 code segment에는 접근이 가능하게 되는것이군요.

다만 객체가 생성(heap 공간)되지는 않았기 때문에, 멤버 변수에는 접근이 불가능 해서 segmentation fault가 발생한 것이고요.

제가 이해한 것이 맞나요?

익명 사용자의 이미지

객체의 포인터가 null 이라도 어째튼 함수는 형성되고, obj->ShowYourName() 이 함수의 주소를 나타낸다.

라는 식의 얘기도 또한 아닙니다.
그런식의 얘기는 그 동작에 대해 잘 정의하고 있는겁니다.
안되니.. 되니.. 그 이유가 뭔지 하는 얘기는 아무 쓸모가 없습니다.
죄다 undefined behavior니까 말입니다.

이래서 된다. 저래서 안된다.
그런게 그렇게 잘 정해져 있으면 undefined behavior가 아닙니다. ^^

C++ 컴파일러를 어찌 만드느냐에 따라서 이럴 수도 있고 저럴 수도 있는겁니다.

lsfeel0204의 이미지

그렇군요..제일 정확하게 아는 방법은 C++ 스펙을 보면 되겠군요...

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.