2013-05-14 5 views
0

저는 C (24 시간 만에 Sam 's Teach Yourself C 읽기)를 배우고 있습니다. 나는 포인터와 메모리 할당을 통해 얻었지만, 이제는 구조 내부에서 그들에 대해 궁금해하고 있습니다.구조체 및 malloc의 포인터 이해

나는 놀기 위하여 아래에 약간의 프로그램을 썼다. 그러나 나는 그것이 좋은지 아닌지 확실하지 않다. 아무런 문제없이 컴파일 된 -Wall 플래그가있는 gcc가있는 Linux 시스템에서 컴파일되었지만 100 % 신뢰할 수 있는지 확실하지 않습니다.

아래에서 수행 한 것처럼 포인터의 할당 크기를 변경하거나 인접한 메모리를 스테핑 할 수 있습니까? 나는 구조체의 변수를 before/after 변수를 검사 해 보았지만 구조체 요소가 메모리에 연속적으로 저장되어 있는지 알지 못한다. (구조체에 대한 포인터가 전달 된 이후로 추측하고있다. 함수 및 포인터 위치를 통해 조작 된 구조). 또한 포인터 위치의 내용에 액세스하여 반복 할 수 있으므로 연속적이면 아무 것도 덮어 쓰지 않도록 할 수 있습니까? 내가 묻는 한가지는 어떻게 메모리를 망쳐 놓고 디버깅하여 이런 식으로 깨뜨릴 수 있는지를 아는 것입니다. 의 크기가 내 there

종류, 안부, 메모리 누수가 정말 좋아

+5

내 아 ... "24 시간 자신에게 C를 가르쳐". [C 태그 위키] (http://stackoverflow.com/tags/c/info)에 책 목록이 있습니다. X 일/시간/분으로 C를 가르치는 광고에서 벗어나십시오. – Mat

+0

내가 24 시간 만에 로켓 발사를 배울 수 있다면 !! –

+0

@narnie 서둘러주세요. 종말이 내일 저녁이라도 정말로 소중히하는 기억. –

답변

1

없음, 당신이 수를 change.kj하지 않았다하지 못하기 때문에 내가 뭔가를 생각하고

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

struct hello { 
    char *before; 
    char *message; 
    char *after; 
}; 

int main(){ 
    struct hello there= { 
     "Before", 
     "Hello", 
     "After", 
    }; 
    printf("%ld\n", strlen(there.message)); 
    printf("%s\n", there.message); 
    printf("%d\n", sizeof(there)); 
    there.message = malloc(20 * sizeof(char)); 
    there.message = "Hello, there!"; 
    printf("%ld\n", strlen(there.message)); 
    printf("%s\n", there.message); 
    printf("%s %s\n", there.before, there.after); 
    printf("%d\n", sizeof(there)); 
    return 0; 
} 

입니다 런타임시이를 감지하려면 valgrind을 사용하십시오 (Linux의 경우).

당신은 코딩 :

there.message = malloc(20 * sizeof(char)); 
there.message = "Hello, there!"; 

첫 번째 과제 호출 malloc(3)을. 첫째, malloc을 호출 할 때 항상 실패하는지 테스트해야합니다. 그러나 실제로 그것은 일반적으로 성공합니다. 그래서 더 나은 코드를 적어도 :

there.message = malloc(20 * sizeof(char)); 
if (!there.message) 
    { perror("malloc of 20 failed"); exit (EXIT_FAILURE); } 

두 번째 과제는 같은 포인터 there.message에 상수 리터럴 문자열 "Hello, there!"의 주소를 넣어, 당신은 첫 번째 값을 잃었다. 당신은 아마 상수 문자열

strncpy (there.message, "Hello, there!", 20*sizeof(char)); 

은 (방금 strcpy(3)를 사용하지만 버퍼 오버 플로우 조심 수) 것을 복사 할

당신은 strdup(3) (그리고 GNU libc의를 사용하여 일부 문자열 (힙) 새 복사본을 얻을 수 마침내

there.message = strdup("Hello, There"); 
if (!there.message) 
    { perror("strdup failed"); exit (EXIT_FAILURE); }; 

) ... 또한 asprintf(3)있다, 그것은 힙 메모리를 종료 프로그램에서 free 좋은 맛입니다. (그러나 운영 체제 _exit(2) 시간에 프로세스 공간을 supress 것이다.

더 읽기에 대한 C 프로그래밍, memory management, garbage collection.입니다 아마 Boehm's conservative GC

AC 포인터를 사용하는 것을 고려 그냥 메모리 주소 영역. 응용 프로그램이 필요로하는

추신 : 노련한 베테랑 프로그래머라도 C의 수동 메모리 관리는 까다 롭습니다.

+0

오, 와우, 당신도 방금받은 또 다른 질문에 대답했습니다. 나는 기능에 대한 문서를 찾는 시간의 닭을 가지고있다. 그것은 남자 3 페이지에 있다는 것을 몰랐습니다. 전체 라이브러리가 각 기능을 문서화하는 곳이 있습니까? 예를 들어, 수학 라이브러리에서 사용할 수있는 모든 기능은 무엇입니까? – narnie

+0

'man 페이지는 리눅스와 유닉스 시스템에서 오래된 유행이다. 알아 내기 위해서'man man'을 리눅스 터미널에 입력하기 만하면된다. –

+0

맨 페이지를 좋아합니다. 실제로 필자가 전에 작성한 프로그램에 사용하는 구문을 사용하여 내 설명서 페이지를 작성했습니다. 모든 도서관에 대한 문서를 찾는 방법에 대한 조언이 있습니까? gcc 문서에서 찾을 수 있기를 희망했지만 라이브러리 설명이 없습니다. – narnie

0

there.message = "Hello, there!"는 버퍼에 문자열을 복사하지 않습니다. "Hello, there!"라는 문자열을 지닌 새로운 (일반적으로 정적 인) 버퍼에 포인터를 설정합니다. 따라서 작성된 코드에는 메모리 누수가 있습니다 (할당 된 메모리는 프로그램이 종료 될 때까지 해제되지 않습니다).

는하지만, 예,의 malloc은 그 자체로 괜찮습니다. 일반적으로 strncpy, sprintf 또는 유사한 함수를 사용하여 할당 된 버퍼에 내용을 복사합니다.

0

는 포인터의 할당 크기를 변경 OK가 [...]?

허 ? "포인터의 할당 크기 변경"이란 무엇을 의미합니까? 현재 모든 코드는 포인터에 다른 주소를 할당하여 malloc() 바이트를 20 바이트 누설하고 있습니다.

+0

나는 적절한 용어를 가지고 있지 않을 수도 있지만, 내가 의미하는 바는'there'를 초기화 할 때'message' 포인터가 5 + 1 char의 long ("Hello"와 \ 0)입니다. 내가 그것을 한 것처럼 긴 문자열로 변경해야 할 경우 ("Hello, there"로 변경) 어떻게 할 수 있습니까? – narnie

+0

@narnie'there.message = "Hello there";'문자열 리터럴을 사용하기 때문에. –

+0

아, 문자열에 짧은 포인터 길이를 더하면 메모리를 확장 할 필요가 없습니까? 다른 기억을 밟지 않습니까? 그것을 처리하는 컴파일러? – narnie