2013-02-13 3 views
2

빈번한 메모리 할당이 필요한 프로그램에서 작업하면서 설명 할 수없는 동작이 나타났습니다. 해결 방법을 구현했지만 이전 구현이 작동하지 않는 이유가 궁금합니다. 여기 상황입니다 :구조체 realloc 내의 포인터가 괜찮지 만 구조체 내의 포인터에 대한 포인터가 잘못된 포인터 오류로 다시 할당되지 못함

포인터의 메모리 재 할당이 가장 좋은 방법이 될 수 없습니다 (그래서 주시기 바랍니다 경우 나 knwow)

작동은하지만 포인터가 전달 된 경우입니다에 realloc을 새로운 메모리를 할당 할 수 있습니다 리콜 없는. 아래는 내가 임시 버퍼에 파일 데이터를 읽을 예입니다, 다음

내가 너무

typedef struct _my_file { 
     int size; 
     char *data; 
} 

같은 파일 구조 그리고 MEM 재 할당을 가지고 같은 코드를 복사 * 데이터에 대한 적절한 크기와 memcopy 내용을 할당 그래서 : 포인터 포인터의

// cycle through decompressed file until end is reached 
while ((read_size = gzread(fh, buf, sizeof(buf))) != 0 && read_size != -1) { 
     // allocate/reallocate memory to fit newly read buffer 
     if ((tmp_data = realloc(file->data, sizeof(char *)*(file->size+read_size))) == (char *)NULL) { 
       printf("Memory reallocation error for requested size %d.\n", file->size+read_size); 
       // if memory was previous allocated but realloc failed this time, free memory! 
       if (file->size > 0) 
         free(file->data); 
       return FH_REALLOC_ERROR; 
     } 
     // update pointer to potentially new address (man realloc) 
     file->data = tmp_data; 
     // copy data from temporary buffer 
     memcpy(file->data + file->size, buf, read_size); 

     // update total read file size 
     file->size += read_size; 
} 

메모리 재 할당 그러나

실패, 여기 내가 혼란스러워하는 곳입니다. NULL 포인터의 재 할당이 새로운 메모리를 할당한다는 동일한 생각을 사용하여 인수 문자열을 구문 분석하고 각 인수에 대해 포인터에 대한 포인터를 할당 한 다음 해당 포인터가 가리키는 포인터를 포인터에 할당합니다.

typedef struct _arguments { 
     unsigned short int options; // options bitmap 
     char **regexes;    // array of regexes 
     unsigned int nregexes;   // number of regexes 
     char *logmatch;    // log file match pattern 
     unsigned int limit;   // log match limit 
     char *argv0;     // executable name 
} arguments; 

그리고 메모리 할당 코드 : 이것은 구조

: 내가 컴파일 할 때

int i = 0; 
int len; 
char **tmp; 
while (strcmp(argv[i+regindex], "-logs") != 0) { 
     len = strlen(argv[i+regindex]); 

     if((tmp = realloc(args->regexes, sizeof(char **)*(i+1))) == (char **)NULL) { 
       printf("Cannot allocate memory for regex patterns array.\n"); 
       return -1; 
     } 
     args->regexes = tmp; 
     tmp = NULL; 

     if((args->regexes[i] = (char *)malloc(sizeof(char *)*(len+1))) == (char *)NULL) { 
       printf("Cannot allocate memory for regex pattern.\n"); 
       return -1; 
     } 

     strcpy(args->regexes[i], argv[i+regindex]); 

     i++; 
} 

내가 런타임 오류 "realloc을 얻을이 실행 아마 코드를 설명하는 것이 더 쉽습니다 : 유효하지 않은 포인터 "

나는 5 시간 동안 온라인으로 솔루션을 디버깅하고 검색하려고 애 쓰지는 않았지만, 지금 막 두 개의 루프를 돌렸다. 하나는 인자의 수와 malloc을위한 충분한 공간을 세고, 두 번째 루프는 인자를위한 공간을 할당하고 그것을 strcpys한다.

이 동작에 대한 설명은 매우 감사하겠습니다! 나는 정말로 이유를 알고 싶어합니다.

+0

'if ((tmp_data = realloc (file-> data, sizeof (char *) * (file-> size + read_size)) == (char *) NULL) {}' (tmp_data = realloc (file-> data, file-> size + read_size)) == NULL) {}'. 당신은 포인터가 아닌 문자의 배열을 aloocating하고 있습니다. 그리고 당신은 struct realloc에서 같은 종류의 에러를 만듭니다. – wildplasser

+1

'args-> regexes'가'realloc' 호출 전에 초기화 되었습니까? printf ("% p \ n", ...)' – cnicutar

+0

'if (file-> size> 0) free (file-> data); return FH_REALLOC_ERROR;'file-> data를 NULL로 설정하지 않으면 위에서 언급 한 @cnicutar와 같은 방식으로 메모리가 누출됩니다. BTW : 그것은 누출되지 않지만, 해제 된 메모리는 다음 반복에 의해 참조되거나 "해제"될 수 있습니다 (있는 경우). – wildplasser

답변

1

우선 단편

// cycle through decompressed file until end is reached 
while (1) { 
     char **tmp_data; 
     read_size = gzread(fh, buf, sizeof buf); 
     if (read_size <= 0) break; 

     // allocate/reallocate memory to fit newly read buffer 
     tmp_data = realloc(file->data, (file->size+read_size) * sizeof *tmp_data); 
     if (!tmp_data) { 
       printf("Memory reallocation error for requested size %d.\n" 
         , file->size+read_size); 

       if (file->data) { 
         free(file->data) 
         file->data = NULL; 
         file->size = 0; 
       } 
       return FH_REALLOC_ERROR; 
     } 

     file->data = tmp_data; 
     // copy data from temporary buffer 
     memcpy(file->data + file->size, buf, read_size); 

     // update total read file size 
     file->size += read_size; 
} 

번째 단편

unsigned i; // BTW this variable is already present as args->nregexes; 

for(i =0; strcmp(argv[i+regindex], "-logs"); i++) { 
     char **tmp; 

     tmp = realloc(args->regexes, (i+1) * sizeof *tmp); 
     if (!tmp) { 
       printf("Cannot allocate memory for regex patterns array.\n"); 
       return -1; 
     } 
     args->regexes = tmp; 

     args->regexes[i] = strdup(argv[i+regindex]); 
     if (!args->regexes[i]) { 
       printf("Cannot allocate memory for regex pattern.\n"); 
       return -1; 
     } 
... 
return 0; 
} 

몇 주 :

  • 구문 ptr = malloc (CNT * sizeof *ptr);sizeof(type) 변이체보다 더 강력하다.
  • 에서는 StrDup()는 정확히의 malloc + strcpy를() (;) 루프는 루프 본문의 끝에 느슨한 i++;있는 동안() 루프보다 더 쉬운 적은 오류가에 대한
  • 는 AS 같은 않습니다.나 if (!ptr) {}-
  • 이 캐스트가 필요하고 때로는 원치 않는되지
  • if (ptr != NULL) {}보다 읽기 easyer이다 (그것은 또한 loopcondition이 확인되지 않습니다 것이 분명합니다).
+0

조언 해 주셔서 감사합니다. 나는 그 (것)들을 아주 유용하게 발견하고, 지금부터 strdup를 사용할 것이다. 투표 할 수 있다면 투표 할 것이지만 15 명이 필요하다고 말하는 상자가 있습니다. 그리고 여러분은 옳습니다. 왜 다른 변수 i를 만드는 대신 nregexes를 사용하지 않을까요? 추가 정리 및 최적화를 위해 내 코드를 다시 살펴 보겠습니다. 다시 한 번 감사드립니다! – pandoraEudora