포인터 변수를 잡아서 atoi를 할경우의 세그먼트 펄트 처리방법에 대해서 아시나요?

wontop의 이미지

아래 소스에서
atoi에서 세그먼트 펄트가 뜨면서 실행파일이 죽는데 원인을 모르겠습니다.

#include <stdio.h>
 
int main()
{
    char* des[100];
 
    des[0] = 0;
 
    int nTest = atoi(des[0]);
    printf("WONTOP = %d", nTest);
 
    return 0;
}
blueiur의 이미지

char* 를 100개 가지는 des 변수를 생성하셨으면
각 des[0-99] 까지에 메모리를 할당해 주셔야 합니다.

wontop의 이미지

int main()
{
    char* des[100];
 
    des[0] = "9";
 
    int nTest = atoi(des[0]);
    printf("WONTOP = %d\n", nTest);
 
    //InsertStruct(des);
 
    return 0;
}

--------------------------------------------------
그걸 이루던지 이루지 못하던지 사람은 꿈에 이끌리는 법이죠.
'꿈'이라는 이름의 신의 순교자로서의 일생을

--------------------------------------------------
그걸 이루던지 이루지 못하던지 사람은 꿈에 이끌리는 법이죠.
'꿈'이라는 이름의 신의 순교자로서의 일생을

netionics의 이미지

des[0] = 0과 des[0] = "9"는 하늘과 땅차이입니다.
문자열이나 포인터에 대해 잘못 알고 계신 것 같습니다.

:)

wontop의 이미지

프로그램 한답시고 하고 있는데 이정도 실력밖에 안되어서 가슴 아픕니다. ㅠㅠ

int main()
{
    int nTest;
    int i=0;
    char* des[100];
 
    // 큰 따옴표는 문자열의 표시이다.
    des[0] = "0";
    des[1] = "9";
    des[2] = "a";
 
    // 0은 정수값 0이다.
    des[3] = 0;
 
    // 작은 따옴표는 문자 상수이다.
    // 문자 상수는 Char하나를 표현할때 표시한다.
    des[4] = '0';       // '0'은 정수 48과 같음
    des[5] = '9';       // '9'은 정수 57과 같음
 
 
    for(i=0; i<100; i++)
    {
        nTest = atoi(des[i]);
        printf("WONTOP %d = %d\n", i, nTest);
    }
 
    return 0;
}

위 소스에서 des[3], des[4], des[5] 번에는 상수값이 들어가게 되고..

atoi에 들어갔을때 해당 des[3]번에 가르키고 있는 상수값의 포인터에 접근하려고 하므로써
세그먼트 펄트가 뜨는건가요?

이와 같은 경우 des[x]값중 어떤값이 들어가든

문자열의 값일 경우에만 처리할려고 하면 어떻게 해야 하는건가요?

--------------------------------------------------
그걸 이루던지 이루지 못하던지 사람은 꿈에 이끌리는 법이죠.
'꿈'이라는 이름의 신의 순교자로서의 일생을

--------------------------------------------------
그걸 이루던지 이루지 못하던지 사람은 꿈에 이끌리는 법이죠.
'꿈'이라는 이름의 신의 순교자로서의 일생을

klara의 이미지

des[x]의 타입이 뭔지 생각해보세요. char*입니다.

Quote:
des[0] = "0";

이것은 des[0]이 상수문자열인 "0"을 가리키게 한 것입니다.
참고로 이것은 위험한 방법으로 일반적으로 상수문자열을 가리키게 할때는 char*가 아니라 const char*를 이용하는게 바람직합니다.
어찌되었든 딱히 des[0]의 내용을 바꾸려고 하지 않는한은 유효합니다.
Quote:
// 0은 정수값 0이다.
des[3] = 0;

// 작은 따옴표는 문자 상수이다.
// 문자 상수는 Char하나를 표현할때 표시한다.
des[4] = '0'; // '0'은 정수 48과 같음
des[5] = '9'; // '9'은 정수 57과 같음


des[x]는 char가 아니라 char*입니다! 이것들은 전부 포인터에 정수를 대입하고 있는 것입니다.
특히 des[3] = 0에서 0은 정수0이 아니라 널포인터 0입니다.
나머지 두줄은 전부 정수로 형변환되어 포인터 주소를 덮어쓰는 셈이됩니다.

char*가 아니라 double*이라고 생각해보세요.
마지막 두줄은 마치 다음과 같이 적고 있는 것입니다.
double *pd = 5;
포인터와 정수사이에는 형변환이 가능하기 때문에 컴파일은 될더라도, 실제로 5라고 하는 주소에 뭐가 있는지 알수도 없고 일반적으로는 pd가 가리키고 있는 부분에 접근하는 순간 프로그램은 알수없는 상태에 빠져듭니다.
char*의 배열이라 char와 문자열을 혼동하고 계신듯한데, 다음 코드를 보고 뭐가 잘못됬나 생각해보세요. 본질적으로 같은 코드입니다.

double *pd;
pd = 3;
if (*pd == 1.0)
    printf("1.0");

wontop의 이미지

본질적인 문제점에 대해서는 이제 이해가 갈듯 말듯 합니다.

#include <stdio.h>
 
int main()
{
    int nTest;
    int i=0;
    char* des[100];
 
    // 큰 따옴표는 문자열의 표시이다.
    des[0] = "0";
    des[1] = "1";
    des[2] = "9";
    des[3] = "a";
 
    // 0은 널값이 입력되는것이다.
    des[4] = 0;
 
    // 작은 따옴표는 문자 상수이다.
    // 문자 상수는 실제로 그에 해당하는 아스키(숫자값) 값으로 메모리에 저장 된다
    des[5] = '0';       // '0'은 정수 48과 같음
    des[6] = '9';       // '9'은 정수 57과 같음
    des[7] = 57;
 
    for(i=0; i<7; i++)
    {
        printf("des[%d]=%d\n", i, des[i]);
    }
 
    for(i=0; i<100; i++)
    {
        nTest = atoi(des[i]);
        printf("WONTOP %d = %d\n", i, nTest);
    }
 
    return 0;
}

출력값

des[0]=134514000
des[1]=134514002
des[2]=134514004
des[3]=134514006
des[4]=0
des[5]=48
des[6]=57
WONTOP 0 = 0
WONTOP 1 = 1
WONTOP 2 = 9
WONTOP 3 = 0
세그멘테이션 오류 (core dumped)

다음과 같이 출력되는데.

문자상수와 문자열 상수의 차이점은 알겠습니다.

제가 구현하고자 하는건 위 소스에서

    for(i=0; i<100; i++)
    {
        nTest = atoi(des[i]);
        printf("WONTOP %d = %d\n", i, nTest);
    }

이부분에서 atoi에는 문자열이 들어가야 하는데 문자상수가 들어가므로써
발생하는 세그먼트 펄스를 회피하는것입니다.

c함수를 아무리 찾아도 문자열과 문자상수를 구분하는 함수는 존재하지 않는듯 싶은데
구분하고자 한다면 어떻게 해야 하는지요?

즉, atoi에 들어가야 하는건 문자열이 들거야 하는데 해당 변수가 문자열인지 아닌지를 알수 있는 방법을 찾고 싶습니다. ㅠㅠ
--------------------------------------------------
그걸 이루던지 이루지 못하던지 사람은 꿈에 이끌리는 법이죠.
'꿈'이라는 이름의 신의 순교자로서의 일생을

--------------------------------------------------
그걸 이루던지 이루지 못하던지 사람은 꿈에 이끌리는 법이죠.
'꿈'이라는 이름의 신의 순교자로서의 일생을

jick의 이미지

문제를 거꾸로 생각하고 계신 것 같은데, atoi에 문자열을 넣어야 하는데 문자열 대신 이상한 거(문자 상수라든지)를 넣으면 죽는 게 정상입니다. 이건 말하자면 "자동차로 계단을 올라갔더니 맛이 갔어요, 계단을 올라가도 괜찮은 방법은 없을까요?" 이런 식인데 "원래 그러면 안돼요" 말고는 해결책이 없습니다.

모든 문제는 "char *형 변수에 잘못된 포인터를 대입한" 데에서 시작했으므로 잘못된 값을 대입하지 않는 게 해결책입니다. 즉 위에서 des[5] = '0' 같은 표현은 쓰면 안됩니다.

gcc라면 -Wall을 주고 컴파일하면 아마 컴파일러가 경고를 내줄 것입니다. 초보자 입장에서는 모든 경고는 에러와 같으며 경고가 하나라도 났으면 컴파일 실패라고 간주하시는 게 여러 모로 좋습니다.

물론 그래도 des[4] = 0에서는 경고가 안 날 텐데-_- 이 부분은 NULL pointer에 대해서 공부를 좀 하시면 이해가 될 겁니다.

댓글 달기

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