2010-05-15 1 views
6

어제의 malloc() : 내가 가진 답변에서 How should I pass a pointer to a function and allocate memory for the passed pointer from inside the called function?C 프로그래밍 : (포인터에 대한 포인터를 사용하여) 2 차원 배열 내가 질문을 게시했다

, 나는 내가 무엇을하고 있었는지 실수를 이해 할 수 있었다.

지금 새로운 문제에 직면하고 있습니다. 아무도 도와 드릴 수 있습니까?

나는 그래서 내가 2D 배열을위한 메모리를 할당 할 malloc(...)for(...) 루프를 사용 alloc_2D_pixels(...)라는 또 다른 기능, 내 main()에서 포인터 - 투 - 포인터를 전달하고있어, 동적 2 차원 배열을 할당 할.

글쎄, alloc_2D_pixels(...) 함수에서 돌아온 후에 포인터 포인터는 여전히 NULL로 남아 있으므로 포인터를 포인터로 free(...)에 액세스하거나 시도하면 자연히 프로그램이 중단됩니다.

누구든지 내가 여기서 무슨 실수를 저에게 제안 할 수 있습니까?

도움말 !!!

크람


SOURCE : memory에 액세스 할 때 당신의 alloc_2D_pixels 기능에

main() 
{ 


unsigned char **ptr; 
unsigned int rows, cols; 

if(alloc_2D_pixels(&ptr, rows, cols)==ERROR)  // Satisfies this condition 
    printf("Memory for the 2D array not allocated"); // NO ERROR is returned 

if(ptr == NULL)     // ptr is NULL so no memory was allocated 
    printf("Yes its NULL!");   

// Because ptr is NULL, with any of these 3 statements below the program HANGS 
ptr[0][0] = 10;      
printf("Element: %d",ptr[0][0]); 

free_2D_alloc(&ptr); 

} 


signed char alloc_2D_pixels(unsigned char ***memory, unsigned int rows, unsigned int cols) 
{ 
     signed char status = NO_ERROR; 

     memory = malloc(rows * sizeof(unsigned char**)); 

     if(memory == NULL) 
     { 
      status = ERROR; 
      printf("ERROR: Memory allocation failed!"); 

     } 
     else 
     { 
      int i; 

      for(i = 0; i< cols; i++) 
      { 
       memory[i] = malloc(cols * sizeof(unsigned char)); 

       if(memory[i]==NULL) 
       { 
        status = ERROR; 
        printf("ERROR: Memory allocation failed!"); 
       } 
      } 

     } 

    // Inserted the statements below for debug purpose only 
     memory[0][0] = (unsigned char)10;  // I'm able to access the array from 
     printf("\nElement %d",memory[0][0]); // here with no problems 


     return status; 
} 


void free_2D_pixels(unsigned char ***ptr, unsigned int rows) 
{ 
    int i; 

    for(i = 0; i < rows; i++) 
    { 
      free(ptr[i]); 
    } 

    free(ptr); 
} 

답변

3

하나의 실수는 컴파일되지 않는 코드를 게시하는 것입니다. :) 다음은
/*이 스타일 */내 의견이 코드를 수정됩니다 : C에서이 방법으로 다차원 배열을 사용하여

/* Next four lines get your code to compile */ 
#include <stdio.h> 
#include <stdlib.h> 
#define NO_ERROR 0 
#define ERROR 1 

/* prototypes for functions used by main but declared after main 
    (or move main to the end of the file */ 
signed char alloc_2D_pixels(unsigned char*** memory, unsigned int rows, unsigned int cols); 
void free_2D_pixels(unsigned char** ptr, unsigned int rows); 

/* main should return int */ 
int main() 
{ 
    unsigned char** ptr; 
    /* need to define rows and cols with an actual value */ 
    unsigned int rows = 5, cols = 5; 

    if(alloc_2D_pixels(&ptr, rows, cols) == ERROR) // Satisfies this condition 
     printf("Memory for the 2D array not allocated"); // ERROR is returned 

    if(ptr == NULL)     // ptr is NULL so no memory was allocated 
     printf("Yes its NULL!"); 
    else 
    { 
     /* Added else clause so below code only runs if allocation worked. */ 
     /* Added code to write to every element as a test. */ 
     unsigned int row,col; 
     for(row = 0; row < rows; row++) 
      for(col = 0; col < cols; col++) 
       ptr[0][0] = (unsigned char)(row + col); 

      /* no need for &ptr here, not returning anything so no need to pass 
       by reference */ 
      free_2D_pixels(ptr, rows); 
    } 

    return 0; 
} 

signed char alloc_2D_pixels(unsigned char*** memory, unsigned int rows, unsigned int cols) 
{ 
    signed char status = NO_ERROR; 

    /* In case we fail the returned memory ptr will be initialized */ 
    *memory = NULL; 

    /* defining a temp ptr, otherwise would have to use (*memory) everywhere 
     ptr is used (yuck) */ 
    unsigned char** ptr; 

    /* Each row should only contain an unsigned char*, not an unsigned 
     char**, because each row will be an array of unsigned char */ 
    ptr = malloc(rows * sizeof(unsigned char*)); 

    if(ptr == NULL) 
    { 
     status = ERROR; 
     printf("ERROR: Memory allocation failed!"); 
    } 
    else 
    { 
     /* rows/cols are unsigned, so this should be too */ 
     unsigned int i; 

     /* had an error here. alloced rows above so iterate through rows 
      not cols here */ 
     for(i = 0; i < rows; i++) 
     { 
      ptr[i] = malloc(cols * sizeof(unsigned char)); 

      if(ptr[i] == NULL) 
      { 
       status = ERROR; 
       printf("ERROR: Memory allocation failed!"); 
       /* still a problem here, if exiting with error, 
        should free any column mallocs that were 
        successful. */ 
      } 
     } 
    } 

    /* it worked so return ptr */ 
    *memory = ptr; 
    return status; 
} 


/* no need for *** here. Not modifying and returning ptr */ 
/* it also was a bug...would've needed (*ptr) everywhere below */ 
void free_2D_pixels(unsigned char** ptr, unsigned int rows) 
{ 
    /* should be unsigned like rows */ 
    unsigned int i; 

    for(i = 0; i < rows; i++) 
    { 
     free(ptr[i]); 
    } 

    free(ptr); 
} 
+0

안녕 마크! :) 그래, 네가 맞아 내가 제대로 작동하는 코드를 게시 했어야했다. 귀하의 자세한 답변을 주셔서 감사합니다, 나는 그것을 주셔서 감사합니다. – HaggarTheHorrible

2

, 당신은 간접 또 다른 수준이 필요합니다. 지금은 매개 변수가 가리키는 포인터가 아니라 매개 변수 만 수정하면됩니다. 예를 들어,

memory = malloc(rows * sizeof(unsigned char**)); 
// becomes 
*memory = malloc(rows * sizeof(unsigned char**)); 

// and later... 
memory[i] = malloc(cols * sizeof(unsigned char)); 
// becomes 
(*memory)[i] = malloc(cols * sizeof(unsigned char)); 

은 (기본적으로 어디서든 당신이 memory를 사용하고, 당신은 (*memory)를 사용해야합니다, 괄호 만 필요하면 운영자가 올바른 순서로 적용되도록 첨자를 사용하는 경우)

+1

sizeof (unsigned char *)는 unsigned char **가되어야합니다. –

+0

IMHO, shoule은 실제로'* memory = malloc (rows * sizeof ** memory)'와'(* memory) [i] = malloc (cols * sizeof * (* memory) [i])' 'sizeof' 아래에 여분의'*'. 훨씬 더 오류가 없습니다. – AnT

1

또한 초기화되지 않은 rowscols 개의 변수를 사용하고 있습니다.

1

하면 성능에 대한 "최적"입니다.

명확하지 않은 단어 : 그림과 같이 다차원 배열을 사용하거나 초기화하지 마십시오.malloc()을 여러 번 호출하면 실제 그래픽 (인접한 단일 버퍼)이 어디에 저장되어 있는지 잘 매핑되지 않는 일련의 분리 된 메모리 위치가 생성됩니다. 또한, 수백 또는 수천 번해야하는 경우 malloc()은 엄청나게 비쌀 수 있습니다.

또한 malloc()을 자주 사용하고 있기 때문에 정리를 위해 악몽 (그리고 결국 당신을 물린 버그)이기도합니다. 심지어 코드의 주석에서 언급 한 적이 있는데 왜 ... 왜?당신이 절대적으로이 ptr[rows][cols] 일을해야하는 경우

, 더 나은이 같은를 만들 :

signed char alloc_2D_pixels(unsigned char*** memory, 
          unsigned int rows, 
          unsigned int cols) 
{ 
    int colspan = cols * sizeof(char); 
    int rowspan = rows * sizeof(char*); 
    unsigned char **rowptrs = *memory = malloc(rowspan + rows * colspan)); 

    /* malloc failure handling left to the reader */ 

    unsigned char *payload = ((unsigned char *)rowptrs) + rowspan; 
    int i; 
    for (i = 0; i < rows; payload += colspan, i++) 
     rowptrs[i] = payload; 
} 

당신은 단지 하나의 메모리 블록과 모든 것이 한 번에 해제 될 수를 할당하고 그런 식으로 - 도랑을 free_2D_pixels().

+0

아, 과거에 아무도이 질문에 대답하지 않으면 놀랄 것입니다. 크레딧이 만료되는 크레딧 : http://stackoverflow.com/questions/3144132/malloc-in-c-but-use-multi-dimensional-array-syntax/3144577#3144577 여기를 확인하십시오. –