포인터가 가지고있는 데이터를 넣을때 질문..
글쓴이: rriiaa / 작성시간: 화, 2016/02/02 - 4:47오후
int main()
{
int i, index;
char *key;
char table[5];
memset(table,0,sizeof(table));
key=(char *)malloc(sizeof(strlen(key)+1));
for (i=0;i<5;i++) {
index =sizeof(hashtable)/sizeof(table[0]);
scanf("%s",key);
table[i]=*key;
}
}
이런 코드가있습니다.. 코드를 짤라서 그런데
key는 포인터로 사용이 되어야해서 그렇습니다.
여기서 질문이 key가 가지는(?) 데이터를 table에 넣고 싶은데
저렇게 하니 컴파일은 잘되는데 막상 값을 넣어보니
segmantation fault가 나는군요...어떻게 해야 할까요?ㅜㅜ
Forums:
뭘 하려고 하시는지는 모르겠지만
이 코드는 이상하군요. strlen의 반환값은 size_t 타입이고, 이는 구현환경에 따라 결정되는 어떤 무부호(unsigned) 정수형입니다.
거기에 대고 sizeof를 적용하면 뭐 구현환경에 따른 값이 나오겠죠. 아마도 32비트 환경이면 4, 64비트 환경이면 8? 모르긴 몰라도 아마 의도하신 것보다 작은 메모리가 할당될 겁니다.
이게 직접적인 에러의 원인은 아닐 테지만, sizeof(size_t) + 1을 해도 동일한 결과를 얻을 수 있다는 점에서 뭔가 프로그래머의 의도와 일치하지 않는 것 같군요.
key가 잘 초기화된 null-terminated 문자열을 가리키고 있으며 그 문자열을 담을 수 있는 메모리를 할당하고 싶다면, sizeof 없이 곧바로
malloc(strlen(key)+1)
와 같이 호출하는 것이 맞습니다.제시하신 코드에서는 key에 초기값이 없긴 한데, 잘려진 코드라고 하셨으니 아마도 생략된 거겠죠. 원본 코드에도 key에 초기값이 없으면 그게 segmentation fault의 직접적인 원인이 됩니다. 초기화되지 않은 쓰레기값 포인터를 strlen에 넘기면 안 됩니다.
그 외에도 솔직히 제시하신 코드에 대해 드릴 말씀이 여럿 있는데(부주의한 scanf 사용이라던가) 당장 segmentation fault가 뜨는 원인과는 무관해 보이니 넘어가겠습니다. 연습 목적이라면 큰 문제 없을 것 같기도 하고요.
실수 정정
셋째줄의
sizeof(size_t) + 1
를sizeof(size_t)
로 정정합니다.답글 감사합니다^^
하고자 하는것은.. 어떠한 문자열 포인터를 입력으로 받아서 입력받은 포인터로 어떠한 함수를 통해서
그 포인터가 배열에 저장되게 하는 것인데..
우선 malloc부분은 이해가 되서 고쳐야 할것 같습니다 ^^
궁금한게.. 포인터로 계속 연산을 하더라도 초기화가 필요한거 였군요..
char *p;
char s;
p=&s;
라고 하고 p 를 가지고 계속 연산을 하고 함수의 인자로 전달해도 초기화가 필요한건가요?
아니면..초기값 null을 넣으라는 말씀이신가요?
초기화가 권장사항인 건 맞습니다만
초기화하지 않았더라도 그 값을 사용하지 않았으면 문제가 없습니다.(권장할 만한 스타일은 아니지만요.)
제시하신 코드의 문제점은 strlen 함수에 초기화되기 전의 key가 넘겨졌다는 거죠. 원본 코드에서도 그랬다면 고치셔야 합니다.
감사합니다
많이 배우고 갑니다. 감사드립니다^^
table의 각 요소가 문자열을 받나요?
만약 그걸 원하신 것이라면, table[i]도 포인터여야 합니다. 즉 table은 포인터 배열(*table[])이여야 하는 것이죠.
네 문자열을 받습니다.
그렇다면 일반 배열에는 포인터변수의 데이터를 직접 넣을수 없는건가요?
table[i]=*key 라고 해버리면 key가
table[i]=*key
라고 해버리면 key가 가리키는 문자열의 "첫 문자"를 table[i]에 저장한다는 의미입니다.C언어에서 문자열은 단어 그대로 문자의 배열에 불과하고, 특히나 C언어는 배열을 통째로 다루는 게 불편한 편이어서 이런 식의 가변 길이 문자열을 다루기가 좀 짜증스럽습니다. 예컨대 C언어에서 이미 있는 문자열의 복사본을 힙에 생성하려면 strlen-malloc-strcpy의 3콤보를 거쳐야 하죠. C++에서는 string, vector 등의 지원으로 좀 나아지긴 했습니다만 어쨌건 지금 C를 쓰고 계신 건 그럴 만한 이유가 있어서겠죠.
> 이미 있는 문자열의 복사본을 힙에 생성하려면
> 이미 있는 문자열의 복사본을 힙에 생성하려면 strlen-malloc-strcpy의 3콤보를 거쳐야 하죠.
strdup()
꽤나 보편적인 대안이기는 합니다만 유감스럽게도
꽤나 보편적인 대안이기는 합니다만 유감스럽게도 비표준이죠.
C 표준 라이브러리가 strdup을 포함하지 않은 이유가 궁금했던 적도 있었습니다만, 사실 strlen-malloc-strcpy로 자연스럽게 구현되는 걸 굳이 래핑해서 또 다른 라이브러리 함수를 만들 필요는 없었을지도 모르겠습니다.
아무튼, 이식성이 중요한 프로그래밍이라면 제공된 strdup 함수를 사용하는 것보다는 직접 구현해 쓰는 편이 낫지 않을까요.
답변 감사드립니다.
네.. 굳이 C를 써야하는 이유가 있어서 ㅜㅜ
그렇군요.. 3단콤보로 사용해야겠네요 감사합니다!!
댓글 달기