스택과 힙의 용도?

redpig의 이미지

안녕하세요. C언어를 공부중인데요.
책에 보면 '웹서버의 경우 어떨땐 20byte, 어떨땐 2000byte의 요청을 받을수도 있으므로 고정크기의 스택상의 버퍼보다는 힙을 사용하는게 좋다' 고 나와 있는데요.
어차피 스택이든 힙이든 코딩시 얼마를 할당할 건지 정의해 줘야 하는거 아닌가요?
그럼 middle(1000)으로 1000byte를 할당했어도 런타임시 클라이언트의 요청크기에 따라 가변 크기로 힙을 할당하나요?
답변 부탁드립니다.

doldori의 이미지

배열로 잡으면 크기가 고정되어 있어서 그보다 큰 사이즈가 필요해지면
대응할 수 없죠.

int size;
scanf("%d", &size);
char* p = malloc(size * sizeof(*p));

동적할당을 쓰면 이렇게 할 수 있다는 뜻입니다. 사용 후에 free를 써서
해제하는 건 프로그래머의 책임이고요.
seoleda의 이미지

스택의 크기를 정해주다니요?

물론 컴파일할때 최대 스택의 크기를 정해주긴 하지만, 스택의 크기는 프로그램이 실행되면서 가변적으로 변하고, 자동변수와 여러가지 잡다한 정보가 스택에 저장됩니다.

예를들어 다음과 같은 코드가 있을경우에

int f (f1,f2){
    int a,b,c;

}
int main(
    int m1, m2, m3;
    f(m1,m2);
}

main의 첫번째 줄이 실행될 즈음의 스택의 상태가
bottom [m1, m2, m3 ] top

이라고 한다면, f1이 호출되면 스택의 상태가

bottom [m1, m2, m3, f의 ret address, f1, f2, a, b, c] top

과 같이 됩니다. 머 완벽히 저런 순서는 아니고요, 컴파일러나 기종에 따라서, 내부적인 순서는 변하지만, 명확한건 스택에 저장될 변수는 크기가 컴파일 타임에 이미 정해져 있어야 한다는 것입니다.

따라서 네트워크 스트림이나, 사용자 입력같이 크기가 일정하지 않은 데이타를 스택에 저장하기 보다는 힙에 저장하는 것이 좋다고 하는 거고요, dobule f[1000000] 과 같이 너무 많은 크기의 메모리를 할당해 버리면 스택이 다 차버리는 결과가 생겨 프로그램이 중간에 서버릴 수도 있습니다.

머 물론 큰 데이타를 저장하기위해서 스택의 크기를 확 늘려줘도 상관은 없지만, 그렇게 하는 경우는 엾고요, 큰데이타나, 크기를 미리 알수 없는 경우에 " 사용자가 직접 관리가 가능한 " 힙에 저장하는 것이 좋다는 것입니다.

litdream의 이미지

제생각에는 지금 질문하신분은 변수설정을 자동변수로 하느냐, 아니면
메모리를 할당하느냐의 질문 같은데요..
질문 내용이 할당한 메모리 사이즈를 바꿀수 있느냐인데..

자동변수로 할당하셨으면, 그 자체로는 불가능 하고요..
이를테면 char buf[1000]; 이라고 했는데, 이것이 작다면, buf[] 는 사용할수 없습니다.

malloc() 으로 할당하신다면, 그냥 1000바이트를 할당하기보단, size를 먼저
알아보는것이 보통의 사용법입니다.

char *buf = malloc( sizeof(request)); 정도쯤 되겠죠?
도움 되셨길..

삽질의 대마왕...

Hyun의 이미지

seoleda wrote:
...
명확한건 스택에 저장될 변수는 크기가 컴파일 타임에 이미 정해져 있어야 한다는 것입니다.
...
dobule f[1000000] 과 같이 너무 많은 크기의 메모리를 할당해 버리면 스택이 다 차버리는 결과가 생겨 프로그램이 중간에 서버릴 수도 있습니다.
...

음... 설령 그럴까요???
int fun( int a, char *str )
{
    int aarr[a];
    int sarr[strlen(str)];

    ...
    ...
}

이게 가능합니다... 컴파일할 때 스택을 얼마나 쓸지 고정시키지 않고 동작중에 가능하더군요...
함수가 너무 빈번하게 호출되거나 작은 메모리를 빈번히 할당할때는 위의 방법이 좋더군요...

그리고... 스택이 넘치는 경우는 개인적으로 보지 못했습니다. 물론 눅스가 스택을 잘 관리해 주니깐 그것만 믿고 쓰는것이지만... 그것도 한계가 있으니깐 스택에 몇 KByte이상은 잡는건 위험하긴 하겠죠...
경험상 눅스가 윈도그보다 스택을 더 많이 쓸 수 있는것 같더군요... 윈도는... 조금만 써도... 스택 모자란다고... 툴툴대더군요... :evil:


나도 세벌식을 씁니다
doldori의 이미지

박현우 wrote:
seoleda wrote:
...
명확한건 스택에 저장될 변수는 크기가 컴파일 타임에 이미 정해져 있어야 한다는 것입니다.
...
dobule f[1000000] 과 같이 너무 많은 크기의 메모리를 할당해 버리면 스택이 다 차버리는 결과가 생겨 프로그램이 중간에 서버릴 수도 있습니다.
...

음... 설령 그럴까요???

정말입니다. 컴파일러마다 다르긴 하겠지만 gcc와 VC++은 그렇더군요.
버려진의 이미지

제가 예전에 실험해본적이 있는데요.

컴파일 되는 크기는 컴파일러마다 달랐습니다.

하지만 컴파일이 됐다고 안심할건 절대 아니더라구요.

무심코 실행했는데 날아가버린 하드디스크 (아아)

어떻게 그럴 수 있느냐고 물으실텐데 저도 모릅니다. :roll:

Hyun의 이미지

doldori wrote:
박현우 wrote:
seoleda wrote:
...
명확한건 스택에 저장될 변수는 크기가 컴파일 타임에 이미 정해져 있어야 한다는 것입니다.
...
dobule f[1000000] 과 같이 너무 많은 크기의 메모리를 할당해 버리면 스택이 다 차버리는 결과가 생겨 프로그램이 중간에 서버릴 수도 있습니다.
...

음... 설령 그럴까요???

정말입니다. 컴파일러마다 다르긴 하겠지만 gcc와 VC++은 그렇더군요.

음... 아래 코드는... gcc로 쓰고 있는 코드인데... 무슨 말씀이신지...
int fun( int a, char *str )
{
    int aarr[a];
    int sarr[strlen(str)];

    ...
    ...
}

나도 세벌식을 씁니다
seoleda의 이미지

int fun( int a, char *str )
{
    int aarr[a];
    int sarr[strlen(str)];

    ...
    ...
}

이건 몰랐던 내용인데 정말 신기합니다.

예전에 씨언어 배울땐 저런게 안됐던 걸로 기억하는데 참 세상 많이 좋아졌네요. ^^

하지만 가만 생각해보면, 가변적인 크기의 데이타라는게 대부분 사용자 입력이나, 네트웍 스트림 같은 경우인데, 위와 같은 방법이 편리하긴 하지만, 악의적인 공격에 노출되지 않을까 생각합니다.

doldori의 이미지

박현우 wrote:
음... 아래 코드는... gcc로 쓰고 있는 코드인데... 무슨 말씀이신지...
int fun( int a, char *str )
{
    int aarr[a];
    int sarr[strlen(str)];

    ...
    ...
}

VLA를 쓰신다니 얼리 어답터시네요. :)
제가 gcc로 시험해 봤더니 a 값을 백만 정도 주니까 죽던데요.
버려진의 이미지

seoleda님 doldori님 박현우님 세분다 맞습니다. ^^;

서로 다른 내용을 언급하시면서 오해하고 계신 것 같네요.

아무튼 박현우님께서 말씀하신건...

http://gcc.gnu.org/c99status.html 에 보면

variable-length arrays Broken 이라고 나와 있습니다.

해보면 잘 되죠. Missing은 아니고 Broken이 정확히 뭔지는 모르겠습니다.

다른 컴파일러에서도 사용하게 될것 같다면 지양하는 편이 좋겠죠.

Hyun의 이미지

doldori wrote:
박현우 wrote:
음... 아래 코드는... gcc로 쓰고 있는 코드인데... 무슨 말씀이신지...
int fun( int a, char *str )
{
    int aarr[a];
    int sarr[strlen(str)];

    ...
    ...
}

VLA를 쓰신다니 얼리 어답터시네요. :)
제가 gcc로 시험해 봤더니 a 값을 백만 정도 주니까 죽던데요.

흠... 커널인가... 어디서 저 코드들 봤는데... 최근에 사용된 코드군요...

나도 세벌식을 씁니다
cdpark의 이미지

VLA는 C++에서는 표준 기능이죠.
C 언어에서는 95년 표준에는 빠져 있지만 99년 표준에는 들어갔고요.
gcc에서는 자체 확장으로 지원합니다.

단순히 "프로그램"이라고 하지 말고 C 언어 프로그램인지, C++ 프로그램인지 확실히 구분하고 씁시다!!!

doldori의 이미지

cdpark wrote:
VLA는 C++에서는 표준 기능이죠.
C 언어에서는 95년 표준에는 빠져 있지만 99년 표준에는 들어갔고요.
gcc에서는 자체 확장으로 지원합니다.

C++에는 VLA가 없는데요? -.-a 혹시 vector를 말씀하시는 건가요?

cdpark wrote:
단순히 "프로그램"이라고 하지 말고 C 언어 프로그램인지, C++ 프로그램인지 확실히 구분하고 씁시다!!!

정말 그래야 되겠습니다. :)
gimmesilver의 이미지

cdpark wrote:
VLA는 C++에서는 표준 기능이죠.
C 언어에서는 95년 표준에는 빠져 있지만 99년 표준에는 들어갔고요.
gcc에서는 자체 확장으로 지원합니다.

단순히 "프로그램"이라고 하지 말고 C 언어 프로그램인지, C++ 프로그램인지 확실히 구분하고 씁시다!!!

c++에서 vla가 표준인게 맞습니까?
지금 vs.net 에서 테스트를 해봤는데 컴파일이 안되는 데요?

------------------------
http://agbird.egloos.com

lsj0713의 이미지

doldori wrote:
정말입니다. 컴파일러마다 다르긴 하겠지만 gcc와 VC++은 그렇더군요.

어제 x86/Linux 2.6.5/gcc 3.2.3에서 시험해 본 바로는 char buffer[1<<22] 까지 되고 malloc의 경우 malloc(1<<28) 까지 되더군요. (정확한 수가 아니라 근사값입니다) 해당 환경에선 스택 영역이 힙보단 좀 좁은듯 합니다.

cdpark wrote:
VLA는 C++에서는 표준 기능이죠.

C99에는 확실히 VLA(Variable Length Array)가 포함되어 있습니다만... C++98에서 배열 선언시에는 [] 안에 constant-expression이 들어가야 하므로 VLA가 안되지 않습니까?

D1 [constant-expression{opt}]

만약 가능하다면 gcc 자체 확장일 가능성이 큽니다.

zelon의 이미지

가변길이 배열을 stack 에 생성하는 것은 C99 의 표준이 맞습니다. 그리고 아직 C++ 에는 안 올라온 걸로 알고 있습니다. 된다면 g++ 의 확장이 맞을 듯...

그리고 참고로 window programming 의 경우 thread 를 만들 때 thread 의 stack 을 가변 길이로 정하는 것도 가능합니다. ^^

-----------------------------------------------------------------------
GPL 오픈소스 윈도우용 이미지 뷰어 ZViewer - http://zviewer.wimy.com
블로그 : http://blog.wimy.com

이준의 이미지

VLA 라는거..

오늘 처음 알았는데 재미있군요

sparc 에서 어셈블리 코드를 보니까 sp 를 증가 시켜 주는 코드를 만드는군요..

심지어 sizeof도 코드를 생성해 주던데.... ^^; 완전 late binding 이군요..

이경우 소량의 데이타인 경우에는 편리하게 사용 할수 있겠군요..

그러나 대량의 데이타 처리할때는 죽어버리는수가 생길수 있겠네요^^

Hyo-Sung Lee(李曉星/Mark Lee)

KRSF Certified Inline Skate Instructor
Fitness Inline Skate Trainer
Mogul&Freeride Skier
IDOne ski rider
Cafe MogulBuddy/KoreaMogul
E-Leader(C) Programmer

mach의 이미지

이준 wrote:

...
그러나 대량의 데이타 처리할때는 죽어버리는수가 생길수 있겠네요^^

동감입니다.
신중하게 코딩할때는 런타임시 메모리를 측정(예측)해서, 최대 메모리를 넘지 않는 서비스만을 수행하게 하는것이 좋습니다.
특히, 서버 프로그램이라면 더하겠지요.
이를테면, 아주 거대 메모리를 소요하는(비정상적일 수 있는) query라면, 이런 query를 가진 클라이언트는 잘라야겠지요. 백엔드로 넘기기전에 말입니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

댓글 달기

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