2014-01-11 2 views
0

이 프로그램은 'n'명의 학생과 이름을 받아서 (정렬 부분에 havent)을 정렬하기위한 것입니다. 테스트 할 때 내 프로그램이 왜 충돌하는지 파악할 수 없습니다. 코드 :처음 Malloc을 사용하고 프로그램이 깨졌습니다.

#include<stdio.h> 
#include <stdlib.h> 
#define MaxNameLen 100 
int main() { 

    int n; 
    scanf("%d", &n); 
    char *names; 
    char **pointerToNames = (char **) malloc(n * sizeof(char)); 
    if (pointerToNames == NULL) 
     return 0; 

    int i; 

    for (i = 0; i <= n; i++) { 
     names = (char *) malloc(MaxNameLen); 
     gets(names); 
     pointerToNames[i] = names; 
    } 

    for (i = 0; i < n; i++) { 
     free(pointerToNames[i]); 
     free(names); 
    } 
} 
+1

'도착'이란 무엇입니까? – haccks

+0

@haccks http://www.cplusplus.com/reference/cstdio/gets/ – Inisheer

+0

@Inisheer; 죄송합니다! C에서 역사가되다. – haccks

답변

5

세 가지 문제가 있습니다. 여기에

for (i = 0; i <= n; i++) { 

:

malloc(n * sizeof(char)) 

는 두 번째 문제는 읽기 루프

malloc(n * sizeof(char*)) 

해야합니다 첫 번째는 당신이 "배열"충분한 항목을 할당하지 않는다는 것입니다 루프 조건은 한 번만 루프를 반복하도록하여 첫 번째 문제를 해결할 경우 할당 할 수있는 것 이상으로 작성할 수 있습니다. 루프의 조건은 다음 루프와 마찬가지로 i < n이어야합니다.

세 번째 문제는 위의 루프에서 pointerToNames[i]names을 할당으로 그 루프 당신이 마지막으로 읽은 문자열을 가리 킵니다 names을 수행 할 때, 루프

for (i = 0; i < n; i++) { 
    free(pointerToNames[i]); 
    free(names); 
} 

반복 마지막 문자열을 해제한다는 것입니다 따라서 namespointerToNames[n - 1]은 같은 문자열을 가리 킵니다.


다른 두 가지 문제가 발생하면 먼저 할당 실제 pointerToNames 메모리를 해제하지 않는 것을 포함한다. 그리고 당신은 gets을 사용하지 말아야합니다 (오랫동안 사용되지 않았으며 최신 표준에서도 삭제되었습니다). 대신 fgets (또는 gets_s)을 사용하십시오.

또한 don't cast the return of malloc입니다.

1

첫 번째 mallocN 문자를 가리키는 포인터로 메모리를 할당하기위한 것이지만 N 개의 문자를 할당하는 것이므로 훨씬 적은 메모리입니다.

변경이 줄이로

char **pointerToNames = (char **) malloc(n * sizeof(char)); 

: 게다가

char **pointerToNames = malloc(n * sizeof(*pointerToNames)); 

: 무슨 일이 있었

for (i = 0; i < n; i++) { 
     free(pointerToNames[i]); 
     free(names); 

이 지정된 인덱스에 대한 메모리를 해제하지만, 무료 names, 당신이 메모리를 할당하는 데 사용한 임시 포인터가 될 것입니다, 그리고 당신은 cu를 할당했습니다. 각각의 eement에 대한 name의 가치. 따라서 names을 무료로 이용할 필요가 없습니다.

은 아마 당신이 당신의 두 번째 부분 (배열의 각 요소에 대해 메모리를 할당하는 코드)를 변경하는 것이 더 간단 찾을 :
for (i = 0; i < n; i++) { 
     pointerToNames[i] = malloc(MaxNameLen); 
     if (pointerToNames[i]) 
      fgets(pointerToNames[i], MaxNameLen-1, stdin); 
    } 

그래서 names은 더 이상 사용 대신 gets()의, fgets()를 사용한다. for 루프는 0에서 N-1으로 이동하며 N이 아니라는 점에 유의하십시오. pointerToNames[N]은 유효한 배열 요소가 아닙니다.

관련 문제