클래스의 변수는 메모리에 순차적으로 저장이 되나요??
암호화를 공부하다가
간단하게 해보자 하다가 일이커졌네요..
두 클래스가 있습니다.
class high{ public : int flags; int size; }; class low : public high{ public: int value1; int value2; int value3; }; class crypt : public high{ public : char *data; };
보시면 아시겠지만 high에 상속된 low와 crypt클래스가 있습니다..
high에서 상속되는 여러클래스를 죄다 crypt로 변환해서 data에 변환값을주고 다시 원래 클래스로 돌려서 암호화를 하려 하는데요
하다보니 이상한게..
class변수는 메모리에 순서대로 들어가는게 아니었나요!?!
low temp;라고 선언하면..
temp의 주소가 1000 이면 1000에 value1, 1004에 value2, 1008에 value3이렇게 들어가는게 아닌가요?
low클래스는 12바이트니까
crypt의 data를 12바이트로 잡은다음에 때려넣으면 들어갈줄 알았는데
안들어갑니다 어흑그그흐그흐
low temp; temp.value1 = 15; temp.value2 = 22; temp.value3=44;라고 하고..
crypt cr; cr.data = new char[12];
한담에 memcpy(cr, &temp , 12); 이렇게 하니까.. value1값만 cr로 가더라구요..(다른 low인스턴스에 복구시켜보니)
그래서 memcpy말고
이렇게..
cr.data = (char *)&temp;
해보면 얼추 가는거 같은데 거꾸로가 잘 안됩니다.
low temp2 여기에 cr.data를 거꾸로 어떻게 집어넣느냐 이게 문제죠..
이게 안되니까 cr.data = (char *)&temp;이것도 의도대로 진행되었는지도 모르겠구요..
오버로딩으로 해결해보면 어떻게 어떻게 될수도 있을꺼 같은데 그러면 모든 high를 상속받은 클래스에 대해 crypt는
= 연산자 오버로딩을 만들어야하고..그러기엔 너무 귀찮고 'ㅡ' 메모리로 어떻게 해결하고 싶은데..
좋은 방법이 없을까요?
아니 왜 그걸 굳이 char*로 때려넣느냐? 라고 물으시면
high에서 상속받는 모든 클래스를 crypt클래스로 때려넣고
crypt에 키값과 xor걸어서 다시 decrypt하려는게 목적이거든요..
잘못된 부분이 있어 자진 삭제
...
암호화 자체에
암호화 자체에 대해서는 전혀 모릅니다만, 몇가지만 적어보면..
우선 low는 12바이트가 아닙니다. 실제로 sizeof 해보셨나요? 정렬문제를 제외하더라도 최소한 20바이트입니다.
그리고 클래스의 복사를 memcpy로 하는것은 위험합니다. 특히나 예제로 드신거처럼 상속이 껴있을경우는 더욱 그러합니다.마지막으로 적으신 코드는 상속을 하고 있음에도 불구하고 소멸자가 가상함수가 아니기 때문에 동적바인딩을 이용할 경우 메모리 누수가 일어날수 있습니다.
PS 중복등록된 다른 글은 삭제해주세요.
언제 터질지 모르는 폭탄같은 코드입니다.
정렬제한, 패딩, 가상 함수 유무, 가상 상속 유무, 각 멤버에 붙은 접근 제한자 등등 신경 써야 할 것이 한 두가지가 아닙니다.
신경 쓴다고 해결되지도 않을 겁니다. 다른 방식을 쓰는게 건강을 위하는 길입니다.
:)
중복글은 지웠습니다.
중복글은 지웠습니다. 중복이 되어있었는지도 몰랐네요 ㅠ 코드보다 정신줄을 놓아버려서 글올리고 기절했다가 일어났네요
네 당연히.. low크기는 20바이트라는건 아는데요.. 상속된 부분만 볼때 12바이트라 이말이었는데 글을 쓰고보니 대체 머라고 쓴건지 ㅋ
상위 클래스가 8바이트가 있고..
상속된 low의 클래스는 8+12니까..
상속된 crypt클래스에 8+12로 맞춰주고 low의 12를 crypt 12로 복사하고자 저런 뻘짓거리를 하고 있거든요.. 'ㅡ'
소멸자나 머 이런문제는 다 재껴놓고 생각하려다보니 힘드네요..
패딩문제는 어떻게해서든.. 때려맞출까 생각중입니다.. 말은 쉽지만.. ㅠ
어떻게 해서든 클래스를 죽어도 써야한다면 방법이 없을까요..
다른 분이 언급했듯이 그 방법은 안쓰는게 좋습니다.
padding을 1로 했다치더라도 C++인 경우 내부적으로 각 instance 별 할당된 memory 크기와 구조가 컴파일러마다 천차만별입니다. (심지어 같은 컴파일러일지라도 버전따라 틀려질 수 있습니다.)
예를 들어
1) 가상함수 삽입 시 각 instance 마다 보이지 않는 vtable 생성
- 아마 가상 함수가 없으면 없으리라 생각됩니다만, 모든 컴파일러가 보장하는지는 모르겠군요.
2) 예를 드신 경우는 아닙니다만, multi 상속을 받는 경우, member function pointer 크기가 가변이거나(vc++), 12(16? 가물 가물)바이트인가?(gcc)일 수도 있습니다.
3) debug 모드나 compiler option에 따라 instnace에 숨겨진 정보가 있을 수 있습니다.
4) source 상 instance member가 순서대로 memory에 있다는 보장이 없습니다.(아마도? 이건 저 자신도 좀 애매하군요. --;)
5) 그 외 또다른 요인이 있을지 모르겠습니다. C++ 해본지 하도 오래되서 가물 가물...
C라면 모를까, C++이라면 처음부터 저런 방법 구현은 안하는게 속 편하실 것 같군요.
굳이 사용하시겠다면 일단 사용 컴파일러나 컴파일 설정부터 정보 공개하시면 다른 분이 도움을 주실지도...
인용: 4) source 상
class widget {
private: int first;
private: int second;
private: int third;
};
접근제한자를 멤버마다 붙이면 컴파일러가 순서를 맘대로 정할 수 있습니다.
:)
일단 원하시는 것이 C++ class를 c 구조체처럼 쓰는 것이라면
POD struct에 대한 다음 문서를 참고 하시는 것이 도움이 될 겁니다.
http://en.wikipedia.org/wiki/C%2B%2B_structure#POD-structs
http://www.comeaucomputing.com/techtalk/#pod
POD style 구조체는 다음 항목 포함 금지(may - 컴파일러 의존적인듯)
* 일단 사용자 정의 constructor
* base class
* virtual function들
* private/protected member data(static인 경우 가능)
* 그외 특성들
우와..
이거 그냥 한번하자고 한일이 죽자고 커져버렸군요.. 'ㅡ' 어쩌다가 ㅠ
밤새 고민해봐도 여러가지 충돌도 많고 어휴..답변주신분들께 정말 감사드립니다..
다른방법을 고민해봐야겠네요..
댓글 달기