리눅스에서 포인터와 문자열

lakeyoun의 이미지

게시된 내용들을 보았는데 제가 원하는 명확한 해답이 없는것 같아
질문드립니다.

void DisplayErrorMessage(int err)
{
char *ptr = NULL;
 
    if(err == 0) ptr = "err message1";
    else if(err == 1) ptr = "err message2";
 
    if(ptr) printf("\r\nError Code : %d, msg=%s", err, ptr);
 
}


위에서 ptr을 NULL로 초기화한후 다시 문자열 가리키도록 했습니다.
위와 같이 쓰면 문제가 없는지 또,커널의 메모리 관리에 안전성을 보장 할 수 없습니까?
pokev25의 이미지

c책을 펴시고

포인터 부분을 다시 한번 정독 하시는게 좋겠습니다.

기본적인 부분에 대한 학습이 안되어 있으신것 같네요.

....

포인터는 선언하고 NULL로 초기화를 해야 합니다.

위처럼 문자열이 컴파일되면 어떤형태로 있게될까요? 그리고 그걸 포인터에 할당하게되면 무슨일이 일어날까요?

---

결론만 말씀드린다면 아무문제 없습니다.

jick의 이미지

포인터를 선언하면서 꼭 NULL로 초기화를 해야 하는 건 아니죠.
물론 초기화를 안한 가비지 값이 들어가 있는 걸 dereference 해버리면 당연히 안되겠지만요...

lakeyoun의 이미지

답변감사합니다.
저는 여지껏 이렇게 써왔는데, 어느분이 위와 같이 쓰는 방식은
커널단에서 안정성을 보장 할 수 없으니 쓰지 말라고 해서 고수분들의 조언을 구합니다.

mithrandir의 이미지

커널용 코드를 저렇게 짜지 말란건가요?
아니면 userspace에서 짠 코드가 커널에서 문제있을 수 있단건가요? 그분이 한 얘기가 정확히 뭔지 궁금합니다.

언제나 삽질 - http://tisphie.net/typo/
프로그래밍 언어 개발 - http://langdev.net

언제나 삽질 - http://tisphie.net/typo/
프로그래밍 언어 개발 - http://langdev.net

lakeyoun의 이미지

APP단에서 저런 코딩을 하면 커널에 영향을 미칠 수 있고, 실행에 대한
안정성도 보장 할 수 없고 실행도중 문제가 될 수도 있다는 이야기입니다.
즉, 저렇게 짜면 문제가 있으니 저런 스타일은 사용하지 말라는 이야기 였습니다.

응용 프로그램이 돌다 아래와 같은 메시지를 내고 다운되는 일이 종종 발생하였습니다.
원인 규명을 찾다 나온 이야기였습니다.
//---------------------------------------------------------------------------
Unable to handle kernel NULL pointer dereference at virtual address 000002a0
pgd = c1e98000
*pgd = 00000000, *pmd = 00000000
Internal error: Oops: 0
CPU: 0
pc : [] lr : [] Not tainted
sp : c1b6def4 ip : c1b6df24 fp : c1b6df20
r10: c1b6df28 r9 : 000002a0 r8 : c1b6df24
r7 : 00000000 r6 : 00000000 r5 : 00000000 r4 : 00000000
r3 : 00000000 r2 : c1b6df28 r1 : 000002a0 r0 : 00000001
Flags: Nzcv IRQs on FIQs on Mode SVC_32 Segment user
Control: C000317F Table: 31E98000 DAC: 00000015
Process ap70k (pid: 601, stackpage=c1b6d000)
Stack: (0xc1b6dee4 to 0xc1b6e000)
dee0: c00578cc c00577a8 80000013 ffffffff 00000001 00000000 c1b6c000
df00: 000000c7 00000000 c1ebdec0 c1b6df74 00000001 c1b6df54 c1b6df24 c00578cc
.... 이하생략
//------------------------------------------------------------------------

tj의 이미지

그건 그냥 커널 버그구요. 무슨 배포판 쓰시는 지 모르겠지만 옛날 거면 업데하시고, 그 후에도 그러면 버그리포팅 하세요. 위에 적으신 프로그램과는 전혀 상관없어요.

lovewar의 이미지

ptr의 Null pointer dereference를 방어하기 위해서는 다음과 같은 추가적인 로직으로 방어를 해 보시기 바랍니다.

void DisplayErrorMessage(int err)
{
    char *ptr = NULL;
 
    if(err == 0) ptr = "err message1";
    else if(err == 1) ptr = "err message2";
    else ptr = NULL;                              /* if -else, if - else if - else 의 구조를 유지하는 것이 좋을것 같습니다. */
 
    if(ptr != NULL) printf("\r\nError Code : %d, msg=%s", err, ptr);      /* ptr의 명시적 유효성 점검(추가로 embedded 개발시 printf 사용을 금지하는 경우도 있으니 확인해 보시기 바랍니다.) */
}

tj의 이미지

무슨 변수든 선언시 초기화보다 필요한 시점에 초기화하는 편이 나은 경우도 많이 있습니다. 그래야 실수하면 컴파일러가 초기화 안하고 쓴다고 알려주죠.

cinsk의 이미지

string literal(문자열 상수)은 static lifetime을 갖기 때문에, 프로그램이 끝날 때까지 쓸 수 있습니다. 따라서, 위 코드는 아무런 문제가 없습니다.

--
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://www.cinsk.org/cfaqs/

rgbi3307의 이미지

static lifetime은 외부 변수이거나 변수의 형지정(static)에 의해서 결정되는 scope입니다.

"string literal(문자열 상수)은 static lifetime을 갖기 때문에, " <-- 이것은 어디에 있는 표준인가요?

처음 발제자의 코드에서 문자열 상수의 lifetime은 char *ptr의 형지정에 의해서 결정됩니다.
ptr은 내부 포인터 변수이므로 함수 내부에서만 통용되고,
함수 인자로 전달된 err 정수값에 의한 if 조건안에서 문자열 상수가 할당됩니다.
ptr에 할당된 문자열 상수는 DisplayErrorMessage() 함수를 벗어나면 소멸됩니다.
따라서, 처음 발제자의 코드는 정상적으로 실행됩니다.

그런데, ptr 포인터 변수에 static lifetime을 아래와 같이 부여하면 어떤일이 발생하나요?
실행결과를 보시고, cinsk님이 말씀하신,
"string literal(문자열 상수)은 static lifetime을 갖기 때문에, 프로그램이 끝날 때까지 쓸 수 있습니다. 따라서, 위 코드는 아무런 문제가 없습니다."
에 대하여 해명 부탁합니다.

#include <stdio.h>
 
void DisplayErrorMessage (int err)
{
    static char *ptr = NULL;
 
    if(err == 0) ptr = "err message1";
    else if(err == 1) ptr = "err message222";
 
    if(ptr) printf("\r\nError Code : %d, msg=%s", err, ptr);
}
 
int main ()
{
    DisplayErrorMessage (0);
    DisplayErrorMessage (2);
    return 0;
}
 
((실행결과))
 
Error Code : 0, msg=err message1
Error Code : 2, msg=err message1

From:
*알지비 (메일: rgbi3307(at)nate.com)
*틈틈히 커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

From:
*알지비 (메일: rgbi3307(at)nate.com)
*커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

asiawide의 이미지


문자열 상수는 굳이 예를 들자면 이런게 아닐까요?

1 #include
2
3 char* test1(void)
4 {
5 char* test = "hello!";
6
7 return test;
8 }
9
10 int main(void)
11 {
12 char* x;
13
14 x = test1();
15
16 printf("%s\n", x);
17
18 return 0;
19 }

실행

hello!

jick의 이미지

> ptr에 할당된 문자열 상수는 DisplayErrorMessage() 함수를 벗어나면 소멸됩니다.

...이분은 참...

rgbi3307의 이미지

ptr에 할당된 문자열 상수는 DisplayErrorMessage() 함수에서 참조 되었다가
소멸된다고 판단하는 것이 맞습니다.

다만, 문자열 상수 그 자체는 static storage 영역에 남아 있고,
포인터 변수 ptr을 통해서 참조한다. 이렇게 말하지 못한 부분은 죄송합니다.

그러나, ptr을 static으로 선언하면(여기에 lifetime 의미를 부여하는 것이 맞습니다)
ptr은 프로그램이 끝날때까지 문자열 상수를 계속 가지고 있는 것입니다.

From:
*알지비 (메일: rgbi3307(at)nate.com)
*틈틈히 커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

From:
*알지비 (메일: rgbi3307(at)nate.com)
*커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

neogeo의 이미지


원 글을 다시읽어보세요

Quote:

ptr에 할당된 문자열 상수는 DisplayErrorMessage() 함수에서 참조 되었다가
소멸된다고 판단하는 것이 맞습니다.

ptr 이라는 pointer variable 이 소멸되는 것이지, string literal 은 소멸되지 않습니다.

전형적인 말장난 딴지군요.

static variable 과 string literal 의 lifetime 이 다른가요?

Neogeo - Future is Now.

Neogeo - Future is Now.

ymir의 이미지

ANSI C Standard (ANSI X3J11/88-090) (Published May 13, 1988)

http://flash-gordon.me.uk/ansi.c.txt

3.1.4 String literals
...
Semantics

A character string literal has static storage duration and type
``array of char ,'' and is initialized with the given characters.
...

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

rgbi3307의 이미지

static lifetime과 static storage는 의미가 다릅니다.
더구나,처음 발제자의 코드를 "static lifetime"이라는 전제로 설명한 것은
제가 소스코드에서 보여드렸듯이 문제가 있습니다.
문자열 상수는 "static storage"이기 때문에... 라는 전제로 설명했다면, 제가 궂이 반박하지 않았을 것입니다.

From:
*알지비 (메일: rgbi3307(at)nate.com)
*틈틈히 커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

From:
*알지비 (메일: rgbi3307(at)nate.com)
*커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

ymir의 이미지

storage class 가 static 인 것들은 모두 static lifetime 을 갖습니다.
위 문서에서는 static storage duration 이라고 되어 있습니다.

본래의 질문글에서는 입력값이 범위를 벗어난 경우 아무런 액션도 하지 않도록 작성되었기 때문에, 적절하게 작성되어 있습니다.
예시하신 코드는 static 변수의 특성에 대해 설명하는 것이고, 입력 값에 대한 예외처리를 적절히 하지 않은 경우 발생하는 문제점에 대한 설명이지, 본글의 주제나 string literal 의 특성과는 무관합니다.

string literal 은 static 이나 global 변수와 마찬가지로 data segment 에 로드됩니다. 즉, 프로그램이 초기화 되는 순간부터 존재하고, 프로그램이 끝날때까지 유효합니다.
따라서 (static 이 아닌) local ptr 변수는 소멸되더라도, 얘가 return 한 string literal 의 주소는 여전히 유효합니다.

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

rgbi3307의 이미지

ymir님은
storage class = static = static lifetime = static storage duration 을 같은 의미로 보시는거죠?
그럼,
처음 발제자의 코드를 아래와 같이 여러번 호출하면 어떻게 동작합니까?
DisplayErrorMessage (0);
DisplayErrorMessage (2);
DisplayErrorMessage (3);
...

From:
*알지비 (메일: rgbi3307(at)nate.com)
*틈틈히 커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

From:
*알지비 (메일: rgbi3307(at)nate.com)
*커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

jick의 이미지

만약 저렇게 여러 번 호출하는 게 문제가 된다고 생각하신다면 어떻게 문제가 되는지 얘기를 해주시고,

그게 아니라 여러 번 호출하는 과정을 자세히 살펴봄을 통해 지금까지 언급이 안된 새로운 사실을 알 수 있다면 그 사실을 직접 얘기해 주시는 게 좋지 않을까요.

turningPoint의 이미지

막연히 이래서 써도 된다/안된다가 아니라 왜 앞서간 선구자들이 어떠한 과정에 의해 그 결과를 도출했는가 라는 의문을 품고 그들의 사고방식을 들여다 볼 필요가 있습니다.

저도 키즈넷부터 흘러흘러 아직까지 kldp를 사용하고 있지만 (최근 아이디를 잊어먹어서 다시 가입했음) :-(

제가 보기엔 OP가 대면한 문제 "문자열 포인터변수를 NULL로 초기화한후 다시 literal을 가리키도록 했을때 메모리관리에 안정성을 보장할수 있나?"에 cinsk님 답변이 문제가 있다고 생각하지 않습니다.

--- code.s      2010-11-10 13:58:18.000000000 +0900
+++ code2.s     2010-11-10 13:58:28.000000000 +0900
@@ -1,33 +1,31 @@
-       .file   "code.c"
-       .local  ptr.1780
-       .comm   ptr.1780,4,4
+       .file   "code2.c"
        .section        .rodata
 .LC0:
        .string "err message1"
 .LC1:
-       .string "err message222"
+       .string "err message2"
 .LC2:
-       .string "\r\nError Code : %d, msg=%s"
+       .string "Error Code : %d, msg=%s \r\n"
        .text
 .globl DisplayErrorMessage
        .type   DisplayErrorMessage, @function
 DisplayErrorMessage:
        pushl   %ebp
        movl    %esp, %ebp
-       subl    $24, %esp
+       subl    $40, %esp
+       movl    $0, -4(%ebp)
        cmpl    $0, 8(%ebp)
        jne     .L2
-       movl    $.LC0, ptr.1780
+       movl    $.LC0, -4(%ebp)
        jmp     .L4
 .L2:
        cmpl    $1, 8(%ebp)
        jne     .L4
-       movl    $.LC1, ptr.1780
+       movl    $.LC1, -4(%ebp)
이하 생략

rgbi3307님이 말씀하시고자 하는게 static keyword로 선언시 ptr 변수가 statck frame이 아니라 rodata section에 한번 선언된다는걸 말씀하고 싶어하시는것 같은데, 위의 cinsk님의 한줄 댓글이 이해하는 사람에 따라 controversial comment가 될 줄은 아마 당사자도 몰랐을것 같습니다.

그리고 rgbi3307님이 드신 예시처럼 DisplayErrorMessage (2); DisplayErrorMessage (3); 이렇게 불러질 수 있다는 이야기는 DisplayErrorMessage 함수내에 exception handling 부분이 처리가 안되어 있어(no leak guarantee) 생긴 문법적오류가 아닌 논리적 오류로 보입니다.

그리고 항상 느끼는 부분이지만 컴퓨터와 커뮤니케이션하는 부분보다 사람들과 커뮤니케이션 하는 부분이 더 어려운것 같습니다.
예전 kldp에 글쓸때 anonymous 로 쓰면 나는 겁쟁이 인가 뭐... 이런 비슷한걸로 쓰였는데....

어느 순간 보다 글 쓰기가 무서워짐은 내 지식에 대한 확고함이 없어서기 보다는 좀 더 낳은 방향으로 서로 win-win 하기보다 흑백논리등등을 앞세운 감정적인 싸움으로 번지 경우도 있고 불필요하게 소모적인 싸움에 이끌려 시간을 소비하기 싫어서 입니다. 이젠 진짜 겁쟁이가 되어가는것 같습니다.

부디 ymir,cinsk 님 같으신 분들이 저와 같은 생각을 하지 않으시길 바랄뿐입니다. :-)

yielding의 이미지

> storage class 가 static 인 것들은 모두 static lifetime 을 갖습니다.

>> ymir님은
>> storage class = static = static lifetime = static storage duration 을 같은 의미로 보시는거죠?

우리말을 도데체 어떻게 해석을 하시는지?

최근에 알지비님의 몇 개의 글들을 봤습니다. 공부에 대한 순수한 마음과 열정은 이해가 되는데 너무 성마르고 공부가 짧아 보입니다.
(이 글타래의 질문과 답변, 본인 답변을 다시 한 번 잘 읽어보세요.)

특히 ymir님 께서는 겸손하고 끈기있게 정확한 답변을 달고 계시는데, 그 마음을 읽고, 또 답변에서 베우려는 자세가 필요해보입니다.

Life rushes on, we are distracted

Life rushes on, we are distracted

ymir의 이미지

전혀 아닙니다.
specifier(reserved keyword) 와 일반 용어를 혼동하시면 안됩니다.

storage class 는 automatic 과 static 으로 나뉩니다.
automatic 은 auto/register 변수와 같이 local block 내에서 사용되며, lifetime 역시 호출되어 있는 동안입니다.
static 은 static/global 변수처럼 local block 또는 all block 에서 사용되며, external linkage 를 통해 접근할 수도 있습니다.
static storage class 는 그 특성처럼 program 의 lifetime 과 동일해야 합니다.
static storage duration 은 program 의 lifetime 과 같고, 이는 static(사전적 의미의) lifetime 을 갖습니다.

storage class 에 대한 specifier 로, auto, register, static, extern, typedef 를 들 수 있습니다.

발제하신 분의 코드는 입력값이 0, 1 일 때에만 메시지를 찍고 그 이외의 값이 온 경우에는 아무런 액션도 하지 않겠다는 코드입니다.
의도대로 잘 동작할 뿐더러 별다른 문제가 없는 코드입니다. (물론 const 까지 써준다면 더 좋겠지만 말이죠..)

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

select99의 이미지

정상작동합니다.

pastime의 이미지

string literal은 .rodata 섹션에 위치하며 기본적으로 text segment로 로드됩니다.

ymir의 이미지

아.. 그러네요.. 고쳐주셔서 감사합니다.

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

gloomyr의 이미지

아마도..
nError Code : 0, msg=err message1 하고 .. 출력안되겟죠.. NULL, NULL 이니..

>>
storage class = static = static lifetime = static storage duration
.. 무엇을 말하고 싶으신건지..

lakeyoun의 이미지

여러 고수분들 조언 감사합니다.
많이 배웠습니다.
다만, 제 질문 때문에 감정적으로 흐르지 않았으면 합니다.
다시 한번 감사드립니다!

select99의 이미지

그냥 메모리나 안정성이나.. 아무문제 없는코드인데.. 웬글들이.. 이렇게 길게..ㅡㅡ;;

cwryu의 이미지

문제가 있다면 코드가 문제가 아니라, 근거 없이 커널단의 안정성을 언급하면서 문제를 지적한 그 분이 바로 문제죠.

같이 일할 때 그냥 모르는 사람보다, 모르는데 아는 척 하는 (심지어는 안다고 믿고 있는) 사람이 더 위험 인물.

댓글 달기

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