[지식인] 해시코드로 알아본 string의 메모리 저장방법 | | | UX 정보 |
![]() |
![]() |
/ | 2008.07.03 16:38 |
<form name="articleHeadModifyForm" action="/ArticleHeadModify.nhn"><input name="m" value="modifyInArticle" type="hidden" /><input name="cluburl" value="kaonsi" type="hidden" /><input name="clubid" value="14637374" type="hidden" /><input name="menuid" value="14" type="hidden" /><input name="articleid" value="127" type="hidden" /><input name="targetarticleheadid" value="" type="hidden" />
</form>
|
우수멤버![]() |
![]() |
http://cafe.naver.com/kaonsi/127![]() |
|
---|
using System;
public class B{
public string aa = "Hello";
public B() { //생성자
Console.WriteLine("생성자 해시코드 : {0}", aa.GetHashCode());
}
~ B(){ //소멸자
Console.WriteLine("소멸자 해시코드 : {0}", aa.GetHashCode());
}
}
public class A{
public static void Main(){
B test = new B();
test.aa = "ello";
Console.WriteLine("참조값 해시코드 : {0}", test.aa.GetHashCode());
}
}
컴파일결과
생성자 해시코드 : -694847
참조값 해시코드 : -1518819367
소멸자 해시코드 : -1518819367
여기서 궁금한것이 있습니다.
최초 객체 test를 생성하고 aa라는 문자열 참조변수가 생성되었을 겁니다.
생성당시 해시코드는 (-694847) 입니다.
그런데 객체를 통해 aa에 접근해서 다른 문자열을 넣어주니 해시코드가 바뀌었습니다.
제가 알기론 해시코드는 객체가 생성되면 그 객체를 참조할 수 있는 고유한 값이라고 알고 있습니다.
1. 그렇다면 기존 "Hello"와는 따로 "ello"의 메모리가 새로 생성된 것인지,,??
2. 그래서 참조변수 aa에 "ello"에 대한 참조값이 들어갔다면 기존에 있던 "Hello"를 참조할 수 있는 방법은 없는건지?
3. 메모리상에는 "Hello"가 여전히 존재 하고 있는건지..?
4. 만약 존재한다면 가비지콜렉터의 대상으로 "Hello"의 메모리가 소멸되어야 하는것은 아닌지?
5. 그런데 위에 소멸자를 보면 "ello"의 메모리가 소멸되고 있습니다. 이건 왜 이런건지?
완전 초보입니다..
좀 도와 주십시오~
============================================================================================================
안녕하세요?
C#에서 문자열은 특수한 개념을 가지고 있습니다.
String a = "asd";
위와 같이 a라는 문자열 클래스를 생성하면, 일반적으로 생각하는대로 메모리에 "asd"라
는 상수가 생길 것이고, a라는 변수가 이를 가르킬 것입니다.
그런데 만약에
a = a + "s";
라는 코드를 작성하게 되면, 우리가 직관적으로 생각하듯이 "asd" 라는 문자열 뒤에 "s"가
붙는것이 아닌, 새로운 문자열이 생성됩니다. 즉, "asd" + "s" 인 "asds"라는 문자열이
새로운 공간에 생성되고, a는 이를 가르킵니다. 따라서 해쉬코드가 바뀌게 됩니다.
이러한 특성은 대입문이라서 일어나는 것이 아닌 문자열 변경인 모든 경우에
일어납니다. 즉, 문자열을 변경하고 이를 대입하게되면 새로운 객체가 생성됩니다.
이러한 특성때문에 문자열을 통해 많은 연산을 할 경우 성능을 떨어트리는 직접적인
원인이 될 수 있습니다.
예를 들어 다음과 같은 문자열 연산을 한다고 가정해봅시다.
string myString = "";
for (int i=0; i<100; i++)
{
myString += i.ToSting();
}
위와 같은 코드를 실행하게되면, 각 for문 마다(즉, 100번) 새로운 문자열을 위한 공간이
할당됩니다. 즉, 계속해서 문자열이 새로 생성되는 것입니다.
"1"
"12"
"123"
....
이런 식으로 말입니다..
그럼 이와 원리를 바탕으로 답변하겠습니다..
1. 그렇다면 기존 "Hello"와는 따로 "ello"의 메모리가 새로 생성된 것인지,,??
따로 생성이 되것입니다.
2. 그래서 참조변수 aa에 "ello"에 대한 참조값이 들어갔다면 기존에 있던 "Hello"를 참조할 수 있는 방법은 없는건지?
새로운 대입을 하기전 참조를 다른곳에 저장해두면 가능합니다.
위에서 설명이 부족했거나 빠트린것 같습니다만..
문자열 객체가 아무때나 새로이 생성되는 것은 아닙니다.
어떤 문자열을 저장하고 있다가, 그 문자열이 변경되게 되면 새로 생기게 됩니다.
따라서 어느 문자열에 대해서 두 개의 참조를 생성하고 하나를 변경하게 되면
원래의 것은 남습니다.
예를 들어 a와 b라는 문자열이 있을때,
string a = "temp";
b = a; // 여기까지는 새로운 문자열이 생성되는 것이 아닙니다.
// 문자열에 대한 변경이 없었기 때문입니다.
b = b + "1" // 새로운 문자열 "temp1"이 할당됩니다. 따라서 기존의 참조는 삭제됩니다.
하지만 a는 원래의 참조를 가지고 있습니다.
3. 메모리상에는 "Hello"가 여전히 존재 하고 있는건지..?
그럴 수도 있으며, 아닐 수도 있습니다. 물론 존재하리라 생각이 듭니다. 명시적으로 가비지콜렉터를 호출해주지 않으셨으므로, 남아있을 가능성이 큽니다. 하지만 확신할 수는 없습니다. 그것은 가비지콜렉터의 정책에 대해 확실하게 알아보는 것이 좋을듯 합니다.
4. 만약 존재한다면 가비지콜렉터의 대상으로 "Hello"의 메모리가 소멸되어야 하는것은 아닌지?
맞습니다. 가비지 콜렉터가 동작한다면, 소멸될 것입니다.
5. 그런데 위에 소멸자를 보면 "ello"의 메모리가 소멸되고 있습니다. 이건 왜 이런건지?
소멸자에서 찍어보았다고해서 소멸되는 것이라고 확신하는 것은 틀린 것입니다.
만약 "ello"가 소멸된다고 해도, 객체에 할당되어 있는 것이 "ello"가 맞기 때문에
정상적으로 동작하는 것입니다.
추가 : 위와 같은 문자열을 특성으로인해 성능이 엄청 떨어지는 경우가 있을 수 있습니다.
문자열을 사용하고, 연산하는 것은 일반적으로 너무나 자주 쓰는 것이기 때문입니다.
이러한 문자열의 단점(?)을 해결하기 위해서 닷넷은 StringBuilder 라는 클래스를
제공하고 있습니다. 사용법은 간단합니다.^^; MSDN을 검색하시면 쉽게 아실 수 있습니다.
그럼 좋은 하루 되시길.. 부족한 답변은 쪽지나 메일 또는 다른 답변을 이용해주세요^^
==================================================================================================================
몇주전 사내 세미나였던 박정오 사원의 'StringBuilder'의 사용 의의와 일맥상통하는 부분이 있군요.
개념적인 이야기니.. 퍼포먼스를 고려하시는 개발자분들께선 참고하셔도 좋을 것 같습니다. ^^
[출처] [지식인] 해시코드로 알아본 string의 메모리 저장방법 (가오니) |작성자 쇼티
'프로그래밍 > .Net' 카테고리의 다른 글
DataGridView내에서 Combobox 활용 (0) | 2014.01.17 |
---|---|
리소스 로드하기 (Resource Load) (0) | 2014.01.17 |
장치관리자 USB 정보 list 가져오기 (0) | 2014.01.17 |
Key Event 키 이벤트 발생 안될 때 (0) | 2014.01.17 |
C# Button Multi Line 설정하는 함수 (0) | 2014.01.17 |