C编程:用于2D数组的malloc()(使用指针到指针)

时间:2010-05-15 23:56:01

标签: c pointers malloc multidimensional-array

昨天我发了一个问题:How should I pass a pointer to a function and allocate memory for the passed pointer from inside the called function?

从我得到的答案中,我能够理解我在做什么错误。

我现在面临一个新问题,任何人都可以帮忙解决这个问题吗?

我想动态分配一个2D数组,所以我从我的main()传递一个指针指向另一个名为alloc_2D_pixels(...)的函数,我使用malloc(...)和{ {1}}循环为2D数组分配内存。

好吧,从for(...)函数返回后,指向指针的指针仍然保持为NULL,当我尝试访问或尝试alloc_2D_pixels(...)指针到指针时,程序很自然挂起。

有人能告诉我我在这里犯的错误吗?

帮助!!!

维克拉姆


来源:

free(...)

4 个答案:

答案 0 :(得分:3)

一个错误是发布无法编译的代码:)。以下是我的评论中的更正代码  / *这种风格* /:

/* 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);
}

答案 1 :(得分:2)

alloc_2D_pixels函数中,访问memory时需要另一级间接。就像现在一样,您只修改参数,而不是参数指向的指针。例如,

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);只有在使用下标时才需要括号,以确保以正确的顺序应用运算符)

答案 2 :(得分:1)

看起来,您使用的是未初始化的rowscols变量

答案 3 :(得分:1)

在C中以这种方式使用多维数组对于性能来说是“次优的”。

没有不明确的词语:请不要使用 - 并且绝对不能初始化 - 以您所说明的方式初始化多维数组。多次调用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()中释放。