구조체의 멤버변수를 바꾸는 함수 질문 다시 올립니다.

ShaYEL의 이미지

제가 KLDP를 보게된지가 얼마 안되서 이래도 되는건지는 잘 모르겠는데요, 낮에 올린 글이 좀 난잡하게 되어버린것 같아서 다시 글을 올립니다. 도움 부탁드리겠습니다..

"input.txt" 파일에는 "string1 string2"가 씌어져 있다고 생각하면 될 것 같습니다. new_structure 함수를 이용해서 string1과 string2를 읽어들여 각각 person이라는 구조체의 member1과 member2에 집어넣도록 하고 싶은데, 코드를 실행시켜도 person 구조체가 텅 비어있는채로 남아있습니다.

제가 짠 코드는 대충 이렇습니다

struct A
{
	char *member1;
	char *member2;
	struct list_elem e;
};
 
void
new_structure (FILE *fp, char *data[], struct A *person)
{
	char arr[20];
	char *token;
	int n = 0;
 
	fgets(arr,20,fp);
	token = strtok(arr," ");
	while (token != NULL)
	{
		data[n++] = token;
		token = strtok(NULL," ");
	}
	person->member1 = data[0];
	person->member2 = data[1];
}
 
void
main()
{
	struct A person;
	char *data[2];
 
	FILE *fp = fopen("input.txt","r");
 
	new_structure(fp,data,&person);
	printf("%s\n",person.member1);
	printf("%s\n",person.member2);  //각각 data[0]와 data[1]의 주소에 들어있는 값이 출력되기를 기대했는데
                                          garbage만 출력됩니다.
 
	fclose(fp);
}

이전글에서 조언해주신 분들 말씀처럼 new_structure함수 내에서 data를 만드는 부분이 잘못된거같은데요, 어디서 잘못된 될까요?

chanik의 이미지

코드를 보니 역시 이전 게시물을 보며 상상했던 그 문제로군요..

strtok()이 리턴하는 토큰은 새로 할당된 메모리에 있는 것이 아니고
첫호출때 넘겨받은 arr[20] 공간에 있는 것입니다.

아래 페이지를 보시면 strtok() 동작방식이 잘 설명되어 있습니다.
원본 문자열 중간중간에 구분자 자리에 NULL 문자를 넣어가면서 토큰을 잘라 리턴합니다.
http://forum.falinux.com/zbxe/index.php?document_srl=408126&mid=C_LIB

arr[20] 공간은 new_structure() 실행 시작될때 스택에 할당되고
new_structure()가 리턴하고 나면 수명이 끝나므로 곧 다른 용도로 덮여버리죠.
그 공간을 가리키고 있는 person->member1/2 내용물도 엉망이 되고요.

우선 간단히 해결하시려면,
data[n++] = token; 코드를 data[n++] = strdup(token); 정도로 바꾸면 됩니다.
strdup()은 힙에 새로 메모리를 malloc()하고 token 문자열을 복제해서 포인터를 넘겨줍니다.

person->member1/2는 나중에 프로그램 어디에선가 꼭 free()해 주셔야 한다는 것을 잊지 마시고요.

ShaYEL의 이미지

정말 감사합니다. 여러가지를 다시 깨닫게 되네요...
링크해주신 사이트도 공부하기 정말 좋은곳같네요 여러모로 감사합니다^^

댓글 달기

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