-
[그냥] C++ 멤버변수 객체와 정적분석 오류...2022.05.12 PM 08:41
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | //////////////////// /* CMemberClass.h */ //////////////////// #pragma once #include <stdint.h> namespace NamespaceTest { class CMemberClass { private: uint32_t m_uCount; public: void SetCount(uint32_t _uCount); const uint32_t GetCount(); }; static CMemberClass memberClass; /* 9-3-2 위반 해결책 Example 참고해서 작성한 코드*/ } ////////////////////// /* CMemberClass.cpp */ ////////////////////// #include "CMemberClass.h" namespace NamespaceTest { void CMemberClass::SetCount(uint32_t _uCount) { m_uCount = _uCount; } const uint32_t CMemberClass::GetCount() { return m_uCount; } } /////////////// /* CMyClass.h */ /////////////// #pragma once #include <stdint.h> #include "CMemberClass.h" namespace NamespaceTest { /* MISRA C++ 2008, Rule 9-3-2 위반 */ /* class CMyClass { private: CMemberClass m_cMemberClass; // 멤버변수 객체 선언 public: CMemberClass* GetMemberClass(); }; */ /* 9-3-2 위반 해결책 Example 참고해서 작성한 코드*/ class CMyClass { private: CMemberClass* m_pMemberClass; // 멤버변수 객체의 포인터를 선언 public: CMyClass(); // 멤버변수 초기화를 위한 생성자 추가 CMemberClass* GetMemberClass(); }; } ///////////////// /* CMyClass.cpp*/ ///////////////// #include "CMyClass.h" namespace NamespaceTest { /* MISRA C++ 2008, Rule 9-3-2 위반 */ /* CMemberClass* CMyClass::GetMemberClass() { return &m_cMemberClass; // 멤버변수 객체의 포인터를 넘겨주면, 멤버변수 객체의 포인터로 private 인자를 수정할 수 있게 됨 } */ /* 9-3-2 위반 해결책 Example 참고해서 작성한 코드*/ CMemberClass* CMyClass::GetMemberClass() { return m_pMemberClass; } CMyClass::CMyClass() : m_pMemberClass(&memberClass) // 생성자에서 멤버변수 객체의 포인터를 설정. { // 이런식으로 쓰면 Rule 9-3-2에서, 아무튼 m_pMemberClass가 멤버변수가 아니라고 함 ㅡㅡ;; // 근데 위에거랑 사실상 똑같은거 아닌지...ㅋㅋ } // 묘하게 IBM Rhapsody에서 생성된 코드랑 비슷한거 같기도..? } ////////////// /* Test.cpp */ ////////////// #include <iostream> #include "CMyClass.h" #include "CMemberClass.h" int main() { NamespaceTest::CMyClass cMyClass; cMyClass.GetMemberClass()->SetCount(10); /* 클래스의 포인터를 받아서, 외부에서 멤버변수 객체 변경이 가능해서 문제가 됨 */ NamespaceTest::CMemberClass* pMemberClass = cMyClass.GetMemberClass(); pMemberClass->SetCount(20); std::cout << cMyClass.GetMemberClass()->GetCount() << std::endl; /* 20이 출력됨 */ return 0; } | cs |
클래스의 포인터를 넘기지 말라고 하는데...
클래스를 멤버변수로 선언해서 주소값 넘기는건 안되고, 클래스 포인터를 멤버변수로 선언한 다음 생성자에서 클래스 주소를 받는건 괜찮다고 하니... 둘다 똑같은거 아닌가...? ㅋㅋㅋ
외부에서 클래스 포인터 받아가지고 조작할 수 있는건 똑같은거 같은데... 전자는 안되고, 후자는 된다니! 내로남불이야아아아앗!!
요것은 MISRA C++ 2008 규칙 캡쳐입니다 ㅋㅋ
댓글 : 6 개
- 카페인 중독자
- 2022/05/12 PM 09:11
전자는 스텍 후자는 힙때문아니에요?
- 뀨읭
- 2022/05/12 PM 09:20
제 생각엔 딱 붙어있는거랑(멤버변수를 클래스로 선언), 떨어져있는걸 붙인거(멤버변수를 클래스 포인터로 선언후 포인터 대입)랑 차이라고 생각하고 있습니다 ㅋㅋ
- 카페인 중독자
- 2022/05/12 PM 09:40
스텍은 스코프를 빠져나가면 사라지기때문에 만약
사라진다기보다 나중에 다른값으로 바뀔수있기때문에
MyMemberClass* a;
{
MyClass b;
a = b.Get MemberClass();
}
a->GetCount();
같은짓을 하면 에러나기때문에 막는것같은데요
사라진다기보다 나중에 다른값으로 바뀔수있기때문에
MyMemberClass* a;
{
MyClass b;
a = b.Get MemberClass();
}
a->GetCount();
같은짓을 하면 에러나기때문에 막는것같은데요
- 카페인 중독자
- 2022/05/12 PM 09:42
MyMemberClass를 힙에 올려두면 사라지지않고 남기때문에 에러가 안나고요
- 뀨읭
- 2022/05/12 PM 10:11
스택, 힙 문제가 중점이 아닌거 같은 이유는, 동적할당을 통해서 힙 메모리 사용하지말라고 되있어서 그렇습니다! (Rule 18-4-1)
- 카페인 중독자
- 2022/05/12 PM 10:15
Static으로 해놓고있었네요
user error : Error. B.