C : 스택?

익명 사용자의 이미지

왜 main펑션의 첫번째 초기화 안된 변수의 값은 - 인가요?
덕분에(?) pointer의 경우 stack(?) 부분을 refer, 그 결과
dereferring 해서 assignment까지 되는 군요.
무슨 특별한 이유라도 있나요?

program1)
#include

int main()
{
int *a, *b, *c;

printf("the address of a, b, c %i %i %i\n", (int)&a, (int)&b,
(int)&c);
printf("the reference of a, b, c %i %i %i\n", (int)a, (int)b,
(int)c);

return 0;
}

result ->
the address of a, b, c -1073742536 -1073742540 -1073742544
the reference of a, b, c -1073742504 1073782272 1074724984

program2)
#include

int main()
{
int *a, i;

printf("the address, the reference, the dereference of a\n");
for (i=0; i<10; i++)
printf("%i %i %i\n", (int)&a, (int)a, *a), a++;
return 0;
}

result ->
the address, the reference, the dereference of a
-1073742536 -1073742504 -1073742472
-1073742536 -1073742500 1073941001
-1073742536 -1073742496 1073818216
-1073742536 -1073742492 1
-1073742536 -1073742488 134513440
-1073742536 -1073742484 -1073742428
-1073742536 -1073742480 1073940784
-1073742536 -1073742476 1074721432
-1073742536 -1073742472 0
-1073742536 -1073742468 134513473

program3)
#include

int main()
{
int *a, i;

printf("the address, the reference, the dereference assigned to 0
of a\n");
for (i=0; i<10; i++)
printf("%i %i %i\n", (int)&a, (int)a, *a=0), a++;
return 0;
}

result ->
the address, the reference, the dereference assigned to 0 of a
-1073742536 -1073742504 0
-1073742536 -1073742500 0
-1073742536 -1073742496 0
-1073742536 -1073742492 0
-1073742536 -1073742488 0
-1073742536 -1073742484 0
-1073742536 -1073742480 0
-1073742536 -1073742476 0
-1073742536 -1073742472 0
-1073742536 -1073742468 0

익명 사용자의 이미지

1) Program 1
the address of a, b, c -1073743484 -1073743488 -1073743492
the reference of a, b, c 134518052 134518032 134513595

int *a라고 선언했으니, &a값은 무의미한 값이니 마이너스값이 나옵니다.

두번째 선언한 a, b, c값이 address값이죠.

(int) & a은

출력 1에서 int *의 값의 address ===> int **의 주소를 int로 바꾼다는

아마도 님은 이부분을 int *의 값(address)를 integer의 값으로 바꾼다고
착각하신 듯 하네요.

그리고 분명히 말씀드리지만, (int)a도 출력은 가능하지만 의미는 전혀!
없는 값입니다.

왜냐하면, 이것은 변수만 선언하고 값을 할당하지 않은 상태에서 그 값을
출력하는 것이므로,

int a;

printf("%d\n", a)

라고 출력하는 것과 마찬가지로 "가능은 하되", "무의미하다"라는 것이죠.

출력하려면,

int *a;
int b;

a= &b;

printf("%d\n", (int)a);

이래야 되겠죠? ^^;

2)
the address, the reference, the dereference of a
-1073743484 134518012 134518044
-1073743484 134518016 1073817264
-1073743484 134518020 1073783056
-1073743484 134518024 1074755808
-1073743484 134518028 134513390
-1073743484 134518032 1073942764
-1073743484 134518036 1074159436
-1073743484 134518040 0
-1073743484 134518044 1
-1073743484 134518048 16

for (i=0; i<10; i++)
printf("%i %i %i\n", (int)&a, (int)a, *a), a++;

님의 코드는 다음과 같이 고치는게 나을 듯 하네요.

for (i=0; i<10; i++, a++)
printf("%i %i %i\n", (int)&a, (int)a, *a);

일단 이건 형식적인 문제고...

아까도 말씀드렸듯이 (int)&a는 무의미하고,
(int)a는 유의미합니다.
그러나 *a는 또 무의미하죠.

왜냐하면 a란 변수는 무언가를 가르켜야 하는데 아무런 실질적인 값을
가르침이 없이 그 가르키는 값을 얻는다는 것은 아무런 의미가 없죠.

게다가...(int)a라는 값도 처음 출력이외에는 무의미한 것이 원래 하나
의 변수값만을 가져야 하는데 그것을 다시 a++함으로서 계속 출력하는
것은 별의미없는 주소만 가르키는 것이 되겠죠?

한가지 더 말씀드리자면, (int)a값을 출력하는 것도 아무 의미가 없죠.

왜냐하면 무언가를 가르키도록 선언된 Pointer to integer의 값을 아무
런 assign없이 출력한다는 것이 아무런 의미가 없는 것이죠.

int a;
print ( "%d\n", a);

이런 것이 출력은 되겠지만 아무런 의미가 없는것과 같은 뜻이죠.

Program 3

the address, the reference, the dereference assigned to 0
of a
-1073743484 134518032 0
-1073743484 134518036 0
-1073743484 134518040 0
-1073743484 134518044 0
-1073743484 134518048 0
-1073743484 134518052 0
Segmentation fault

드디어 segmentation fault가 나죠?...원래 Program 1,2도 잘못 된 프로
그램이라서 이런 메시지가 않 뜨는게 이상할 겁니다.

자 근데, 보십시요.

int *a;라고 하나의 변수만을 선언했는데 님은 a++를 통해서 여러가지
값을 담기를 원하므로 segmentation fault가 않 날래야 않 날수가 없죠.

이렇게 하려면, int a[갯수]만큼 선언해야지 a++하면서 *a=0이 가능한
것 아닐까요?

int a[10];
int *b, i;
b=a;
for ( i=0; i< 10 ; i++,b++)
printf("%d\n", *b);

이 코드도 사실 int a[10]이 메모리만 할당했지 값을 assign하지 않았
으므로 무의미한 값이 나오기는 하겠지만 적어도 segmentation fault
는 않 나겠죠?

일단 여기까지 하시고....

Pointer를 아주 열심히...공부하셔야 할 것 같네요.

아주 열심히요...^^;

익명 사용자의 이미지

Program1 고침

#include

int main()
{
int *a, *b, *c;
int av=100, bv=200, cv=300;

a = &av;
b = &bv;
c = &cv;

printf("the address of av, bv, cv %#x %#x %#x\n", &av, &bv,
&cv);
printf("the value of a, b, c %#x %#x %#x\n", a, b,
c);
printf("the value of a, b, c %i %i %i\n", *a, *b,
*c);

return 0;
}

Program2

#include

int main()
{
int *a,*b, i;

a = (int *) malloc(sizeof(int)*10);
b = a;

printf("%#x\n", b);
for(i=0; i < 10; i++, a++)
*a=i;

printf("the address, the dereference of a\n");
for (i=0; i<10; i++, b++)
{
printf("%#x %i\n", b, *b);
}
printf("a%#x\n", a);
printf("a - 10%#x\n", (a-10));
free(a - 10);
return 0;
}

Program3

#include

int main()
{
int *a, *b, i;

a = (int *) malloc(sizeof(int) * 10);
b=a;
printf("the address, assigned to 0 of a\n");

for (i=0; i<10; i++, a++)
printf("%#x %i\n", a, *a=0);
free(b);
return 0;
}

함 잘 분석해 보십시요.

익명 사용자의 이미지

//int *a라고 선언했으니, &a값은 무의미한 값이니 마이너스값이 나옵니
다.
&a 값은 무의미하지 읺습니다.

//(int) & a은 출력 1에서 int *의 값의 address ===> int **의 주소를
int로 바꾼다는 뜻
//아마도 님은 이부분을 int *의 값(address)를 integer의 값으로 바꾼다
고착각하신 듯 하네요.
제 컴퓨터가 32bit니깐 address가 32bit 즉 4바이트 , 그리고 digital
integer로 출력하려고
int type( sizeof(int) 는 4)으로 캐스트 했는데요.

//왜냐하면 무언가를 가르키도록 선언된 Pointer to integer의 값을 아무
런 assign없이 출력한//다는 것이 아무런 의미가 없는 것이죠.
포인터가 아무것(object)도 가리키지 않을 땐 0이 할당된 상태 입니다.
address 0은 없으니까요.

김 경태님의 실행 결과를 보니, a의 값이 양수 군요,
제 결과를 보시면 a 값이 음수라는 것을 볼 수 있을 겁니다.
물론 우연한(?) 결과 겠지만요, 그리고 &a의 값도 음수 입니다(&b, &c도)
a, b, c모두 펑션내의 변수이므로 스택에 있겠죠, 그래서 음수가 나왔다고
생각 했읍니다(뭐 이부분은 제 추측입니다. 음수로 된 어드레스가
꼭 스택의 어드레스라고는 단정할 수 없읍니다, 제 지식으론)
그리고 segmentation fault도 일어나지 않았읍니다.
언젠간 일어 났겠죠.
제 컴퓨터는 k-6 200mh에 debian potato에 있는 gcc 사용했읍니다.

익명 사용자의 이미지

김경태 wrote..
1) Program 1
the address of a, b, c -1073743484 -1073743488 -1073743492
the reference of a, b, c 134518052 134518032 134513595

int *a라고 선언했으니, &a값은 무의미한 값이니 마이너스값이 나옵 니다.
int *a; 에서

&a가 마이너스값을 가지는 이유를 구체적으로 설명하자면..

예제에서 보면 int *a;가 함수내부에서 선언되었기 때문에

변수 a는 스택에 생성됩니다..

리눅스의 경우 보통 스택이 시작하는 주소는 0xbffffffc입니다..

이곳을 시작으로 아래방향으로 자라나죠..

예제에서는 main함수에서 변수가 선언되었기 때문에 현재의

스택의 주소는 0xbffffffc와 비슷할 겁니다.

0xbffffffc를 2진수로 바꿔보면 최상위비트가 set되었다는것을

알수 있을겁니다..

따라서 signed int형태로 출력을 할 경우 당연히 마이너스 값이 나오게

되죠..

printf("%d",0xbffffffc);를 해보세요..

그럼 저 위의 마이너스 값들과 거의 비슷하게 나올겁니다.

익명 사용자의 이미지

궁금 wrote..
왜 main펑션의 첫번째 초기화 안된 변수의 값은 - 인가요?
덕분에(?) pointer의 경우 stack(?) 부분을 refer, 그 결과
dereferring 해서 assignment까지 되는 군요.
무슨 특별한 이유라도 있나요?


program1)
#include <stdio.h>

int main()
{
int *a, *b, *c;

printf("the address of a, b, c %i %i %i\n", (int) &a, (int)&b,
(int)&c);
printf("the reference of a, b, c %i %i %i\n", (int) a, (int)b,
(int)c);

return 0;
}

result ->
the address of a, b, c -1073742536 -1073742540 -1073742544
the reference of a, b, c -1073742504 1073782272 1074724984

&a,&b,&c가 -값을 가지는 이유는 아래 글에 써놨습니다..
그리고 a,b,c의 값은 완벽한 쓰레기값입니다..


program2)
#include <stdio.h>

int main()
{
int *a, i;

printf("the address, the reference, the dereference of a\n");
for (i=0; i<10; i++)
printf("%i %i %i\n", (int)&a, (int)a, *a), a++;
return 0;
}

result ->
the address, the reference, the dereference of a
-1073742536 -1073742504 -1073742472
-1073742536 -1073742500 1073941001
-1073742536 -1073742496 1073818216
-1073742536 -1073742492 1
-1073742536 -1073742488 134513440
-1073742536 -1073742484 -1073742428
-1073742536 -1073742480 1073940784
-1073742536 -1073742476 1074721432
-1073742536 -1073742472 0
-1073742536 -1073742468 134513473

a값이 쓰레기값이므로 당연히 *a도 쓰레기 값입니다..

*a값을 출력할때 segmentation fault가 나지 않은 것은..

엄청난 운(?)이라고 할수 있습니다..

a에 프로세스가 소유하지 않은 주소값이 들어가 있었다면..

segfault가 발생했을 겁니다..


program3)
#include <stdio.h>

int main()
{
int *a, i;

printf("the address, the reference, the dereference assigned to 0
of a\n");
for (i=0; i<10; i++)
printf("%i %i %i\n", (int)&a, (int)a, *a=0), a++;
return 0;
}

result ->
the address, the reference, the dereference assigned to 0 of a
-1073742536 -1073742504 0
-1073742536 -1073742500 0
-1073742536 -1073742496 0
-1073742536 -1073742492 0
-1073742536 -1073742488 0
-1073742536 -1073742484 0
-1073742536 -1073742480 0
-1073742536 -1073742476 0
-1073742536 -1073742472 0
-1073742536 -1073742468 0

여기서 *a=0에서 segfault가 나지 않은것 또한 운(?)이라고 할수 있죠)

익명 사용자의 이미지

제가 고친 프로그램 1의 결과가...

the address of av, bv, cv 0xbffff978 0xbffff974 0xbffff970
the value of a, b, c 0xbffff978 0xbffff974 0xbffff970
the value of a, b, c 100 200 300

라고 나옵니다.
(위는 Linux실행결과입니다)

님의 말씀이 맞는 것 같군요.

또 한수 배웠습니다.

그런데...스택 번지가 Oxbffffffc에서 -로 빼주는 것은 Kernal의 어디를
보면 알수 있는 것인지..궁금하네요.

기왕 알려주시는 김에 그것도 알려주시면 고맙겠습니다.

아...그리고 님이 말씀하신 주소인 Oxbffffffc와 첫번째 변수인0xbffff978
와는 상당한 값의 차이가 있는데 그 사이에는 어떤 자료가 들어가는지도
알고 싶군요.

익명 사용자의 이미지

garbage value라고 예상은 했읍니다만,
제 행운은 엄청났읍니다. i카운트를 170까지 올릴동안
segmnt. fault가 일어나지 않더군요.
하긴 임의(?)의 주소를 어쩐 객체가 있는 지도 모른 상태에서
dereference해도 실행시켜 주기도 했으니깐요.

익명 사용자의 이미지

김경태 wrote..
제가 고친 프로그램 1의 결과가...

the address of av, bv, cv 0xbffff978 0xbffff974 0xbffff970
the value of a, b, c 0xbffff978 0xbffff974 0xbffff970
the value of a, b, c 100 200 300

라고 나옵니다.
(위는 Linux실행결과입니다)

님의 말씀이 맞는 것 같군요.

또 한수 배웠습니다.

그런데...스택 번지가 Oxbffffffc에서 -로 빼주는 것은 Kernal의 어디를
보면 알수 있는 것인지..궁금하네요.

이것은 커널과는 상관이 없는 부분입니다.

하드웨어적으로 일어나는 부분입니다..

예를 들어 x86경우에 스택에 eax레지스터를 push한다면

push한 후에 자동적으로 스택포인터가 4만큼 감소합니다.

다른 아키텍처들도 마찬가지겠지요..

기왕 알려주시는 김에 그것도 알려주시면 고맙겠습니다.

아...그리고 님이 말씀하신 주소인 Oxbffffffc와 첫번째 변수인0xbffff978
와는 상당한 값의 차이가 있는데 그 사이에는 어떤 자료가 들어가는지도
알고 싶군요.

커널에서 0xbffffffc부터 아랫쪽으로 argv와 env관련 데이터들을 집어넣습니다.

그리고 프로그램의 실제 시작주소도 main함수가 아니라 _start이기 때문에..

main함수가 호출되기까지 또 다른 자료들도 그 사이에 들어가게 되겠죠..

p.s 반드시 0xbffffffc이 아닌 그냥 일반적인 경우입니다.
하지만 이 값이 아닌 경우는 잘 모르겠네요..

익명 사용자의 이미지

garbage value -1073742536에 offset 6000(계속 되는 데 까지 i.e.*a
가 fault를 일으키는 카운터가 늘도록)으로 늘였더니,
i 카운터가 1499가 되도록 fault를 안 일으키더군요.
(그 다음에도 카운터는 2이 더올랐지만 1500이 아니고 1로
돌아온 다음 다시 2로 증가하고 fault, 물론 어떤 경우는
뒤죽박죽으로 변한 경우도 있었읍니다. total 6000=1500*4)
도대체 이 넓은 영역은 어디일까요?

#include

int main()
{
int *a, i;

a=(int *)((-1073742536)-6000);
printf("count, the address, the reference, the dereference
assigned to 0 of a\n");
for (i=0; i<10000; i++)
printf("count(%i) %i %i %i\n",i+1, (int)&a, (int)a, *a=0), a++;
return 0;
}

댓글 달기

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