2017-01-28 7 views
-1

다음은 메모리 할당을 검사하기 위해 작성한 샘플 프로그램입니다.메모리는 스택, 힙에 어떻게 배열됩니까?

[email protected]:~/working_dir/pavan/C$ cat mem3.c 
    #include <stdio.h> 
    #include <string.h> 
    #include <stdio.h> 

    /* This is generated by a template program */ 

    typedef struct stru_s{ 
     char str1[4], str2[4], str3[4]; 
    }stru_t; 
    int main(){ 
     stru_t st; 

     char str1[4], str2[4], str3[4]; 

     char *mstr1, *mstr2, *mstr3, *mstr4, *mstr5;; 

     mstr1= (char*)malloc(4); 
     mstr2= (char*)malloc(4); 
     mstr3= (char*)malloc(4); 
     mstr4= (char*)malloc(8); 
     mstr5= (char*)malloc(16); 

     strcpy(str1, "aaa"); 
     strcpy(str2, "bbb"); 
     strcpy(str3, "ccc"); 
     strcpy(mstr1, "xxx"); 
     strcpy(mstr2, "yyy"); 
     strcpy(mstr3, "zzz"); 

    return 0; 
    } 

아래는 gdb를 사용한 메모리 검사입니다.

[email protected]:~/working_dir/pavan/C$ gdb mem3 
    GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.el6_4.1) 
    Copyright (C) 2010 Free Software Foundation, Inc. 
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 
    This is free software: you are free to change and redistribute it. 
    There is NO WARRANTY, to the extent permitted by law. Type "show copying" 
    and "show warranty" for details. 
    This GDB was configured as "x86_64-redhat-linux-gnu". 
    For bug reporting instructions, please see: 
    <http://www.gnu.org/software/gdb/bugs/>... 
    Reading symbols from /home/xkumapu/working_dir/pavan/C/mem3...done. 
    (gdb) b 1 
    Breakpoint 1 at 0x4005f0: file mem3.c, line 1. 
    (gdb) r 
    Starting program: /home/xkumapu/working_dir/pavan/C/mem3 
    [Thread debugging using libthread_db enabled] 

    Breakpoint 1, main() at mem3.c:17 
    17   mstr1= (char*)malloc(4); 
    Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.192.el6.x86_64 
    (gdb) n 
    18   mstr2= (char*)malloc(4); 
    (gdb) n 
    19   mstr3= (char*)malloc(4); 
    (gdb) n 
    20   mstr4= (char*)malloc(8); 
    (gdb) n 
    21   mstr5= (char*)malloc(16); 
    (gdb) n 
    23   strcpy(str1, "aaa"); 
    (gdb) n 
    24   strcpy(str2, "bbb"); 
    (gdb) 
    25   strcpy(str3, "ccc"); 
    (gdb) 
    26   strcpy(mstr1, "xxx"); 
    (gdb) 
    27   strcpy(mstr2, "yyy"); 
    (gdb) 
    28   strcpy(mstr3, "zzz"); 
    (gdb) 
    30  return 0; 
    (gdb) 
    31  } 
    (gdb) x str1 
    0x7fffffffe330: 0x00616161 
    (gdb) x str2 
    0x7fffffffe320: 0x00626262 
    (gdb) x str3 
    0x7fffffffe310: 0x00636363 
    (gdb) x &str3 
    0x7fffffffe310: 0x00636363 
    (gdb) x &str2 
    0x7fffffffe320: 0x00626262 
    (gdb) x &str1 
    0x7fffffffe330: 0x00616161 <- Aligned to 16 bytes. (from 320 to 330) 
    (gdb) x &mstr1 
    0x7fffffffe358: 0x00601060 
    (gdb) x &mstr2 
    0x7fffffffe360: 0x006010a0 
    (gdb) x &mstr3 
    0x7fffffffe368: 0x006010e0 <- aligned to 40 bytes. (from 0a0 to 0e0) 
    (gdb) x &st.str 
    There is no member named str. 
    (gdb) x &st.str3 
    0x7fffffffe348: 0x00400735 
    (gdb) x &st.str2 
    0x7fffffffe344: 0x00007fff 
    (gdb) x &st.str1 
    0x7fffffffe340: 0xffffe478 <- Aligned to just 4 bytes.(from 340 to 344) 
    (gdb) q 
    A debugging session is active. 

      Inferior 1 [process 12541] will be killed. 

    Quit anyway? (y or n) y 

구조에서 다른 유형의 정렬이 필요한 이유를 설명 할 수 있습니까? 그리고 그것은 힙에 메모리를 사용하는 MCB입니까?

+0

"MCB"란 무엇을 의미합니까? – kalaracey

+0

@kalaracey 메모리 제어 블록. 동적으로 할당 된 각 메모리 덩어리 앞에 추가 될 구조체. 이 구조체에는 두 개의 값 {is_available, size}가 포함됩니다. – pavan

답변

0

GCC는 기본 스택 정렬을 16 바이트로 사용합니다 (-mpreferred-stack-boundary 옵션 참조). 이는 스택에있는 포인터 변수가 16 바이트로 정렬되는 이유입니다.

변수 st은 구조체이며 컴파일러가 가장 효율적이라고 생각하는 것에 따라 압축되지만 일반적으로 바이트는 패딩없이 팩됩니다. 구조체에 4 바이트의 배열 4 개를 넣었으므로 패딩이 필요 없습니다. 따라서 각 항목은 4 바이트 '정렬'됩니다. st 자체는 요소가 없어도 16 바이트 경계에서 시작됩니다.

(구조체에 여러 유형이 혼합되어있는 경우 컴파일러는 워드 정렬을 보장하기 위해 패드를 채 웁니다. 그러나 좋은 이유가있는 경우 패딩을 끄는 특성을 사용할 수 있습니다. 예를 들어 일종의 통신 스택 정의)

메모리가 힙에 할당되는 방식 (예 : malloc)은 시스템의 힙 할당 전략 (c 라이브러리 및 OS)의 함수입니다. 다른 할당 전략을 사용할 수도 있지만 이것이 큰 것입니다 주제 (https://en.wikipedia.org/wiki/Heap_(data_structure) 참조)

+0

감사합니다. 이제 저는 스택에서 수행 된 패딩을 이해했습니다. – pavan

0

str1의 0x00616161은 주소가 아예 없으며 "aaa"라는 문자열의 내용 일뿐입니다. 'a'의 ascii 값은 0x61입니다. 따라서 이것이 17 바이트 정렬이라는 진술은 데이터의 잘못된 해석 일뿐입니다.

malloc을 사용하여 할당 된 문자열에는 malloc이 메타 데이터와 같은 자체 하우스 키핑을위한 공간이 필요하기 때문에 각 할당마다 약간의 공간이 있습니다.

마지막으로 스택 변수는 초기화되지 않으므로 가비지를보고있는 것입니다.

+0

롭, 친절하게 도와 주셔서 감사합니다. 또한 16을 위해 17의 오타를 지적 해 주셔서 고마워요. (나는 그것을 바 꾸었습니다). 내 질문의 주된 이유는 스택에 최대 1635 바이트가 걸린 이유입니다. 구조의 4 바이트 -> 예상 됨. 40 바이트 -> 메모리 제어 블록 때문일 수 있습니다. 설명이 필요합니다. 당신이 저를 도울 수 있다면 좋겠다고 생각합니다. – pavan

+0

다른 누군가가 좋은 설명을 해 준 것처럼 보입니다. 지금하고있는 일은 훌륭합니다. 디버거를 사용하여 사물을 파고보고있는 것을 이해하고, 필요한 경우 질문하십시오. –