在C中分配2D数组,仅使用一个malloc

w41d8nur  于 2022-12-03  发布在  其他
关注(0)|答案(1)|浏览(127)

这是我第一次问一个问题,所以我可能做错了什么,我为此道歉。
所以,我在C中做了一个函数来动态分配一个二维数组void**,这样我就可以强制转换它,并使用这个函数来创建一个二维数组char或int,或者如果需要的话。函数如下:

void    **ft_new_arr(size_t row, size_t col, size_t size)
    {
        void    **arr_ptr;
        int     *arr_byte;
        size_t    total_size;
        size_t    y;
    
        if (row == 0 || col == 0 || size == 0)
            return (NULL);
        total_size = (col * sizeof(void*)) + (row * col * size);
        if ((total_size - col * sizeof(void*)) != (row * col * size))
            return (NULL);
        arr_ptr = (void**)malloc(total_size);
        if (arr_ptr == NULL)
            return (NULL);
        memset(arr_ptr, 0, total_size);
        arr_byte = (int *)arr_ptr + col * sizeof(void*);
        y = 0;
        while (y < col) 
        {
            arr_ptr[y] = arr_byte + (y * (row * size));
            y++;
        }
        return (arr_ptr);
    }

我知道的唯一问题是,我可能会浪费一些内存,因为所有的行都将具有相同的大小,但我想这并不是那么糟糕。
为了测试它,我做了一个函数,将一个字符串(char *)拆分为空格(ASCII中为0到32),并在之前分配的数组中的每一列填入该字符串的一个单词,然后我做了一个函数来打印我的数组。
这是我的分裂函数:

static int    get_nb_words(char *str)
{
    int    i;
    int    res;

    i = 0;
    res = 0;
    while (str[i])
    {
        while (str[i] && str[i] >= 0 && str[i] <= 32)
            i++;
        if (str[i] && str[i] > 32)
        {
            while (str[i] && str[i] > 32)
                i++;
            res++;
        }
    }
    return (res);
}

static int    get_word_len(char *str)
{
    int    i;
    int    tmp;
    int    res;

    i = 0;
    tmp = 0;
    res = 0;
    while (str[i])
    {
        while (str[i] && str[i] >= 0 && str[i] <= 32)
            i++;
        if (str[i] && str[i] > 32)
        {
            tmp = 0;
            while (str[i] && str[i] > 32)
            {
                i++;    
                tmp++;
            }
            if (tmp > res)
                res = tmp;
        }
    }
    return (res);
}

static void    fill_array(char **new_arr, char *str)
{
    int    i;
    int    x;
    int    y;

    i = 0;
    x = 0;
    y = 0;
    while (str[i])
    {
        while (str[i] && str[i] >= 0 && str[i] <= 32)
            i++;
        if (str[i] && str[i] > 32)
        {
            y = 0;
            while (str[i] && str[i] > 32)
            {
                new_arr[x][y] = str[i];
                i++;
                y++;
            }
            new_arr[x][y] = '\0';
            x++;
        }
    }
}

void    ft_printab(char **new_arr, int nb_row)
{
    for (int i = 0; i < nb_row; i++)
        printf("arr[%d] = |%s|\n", i, new_arr[i]);    
}

char    **ft_split(char *str)
{
    int        nb_words;
    int        words_len;
    char    **new_arr;

    nb_words = 0;
    words_len = 0;
    if (!str)
        return (NULL);
    nb_words = get_nb_words(str);
    words_len = get_word_len(str);
    if (!nb_words || !words_len)
        return (NULL);
    new_arr = (char **)ft_new_arr(words_len, nb_words, sizeof(char));
    if (!new_arr)
        return (NULL);
    fill_array(new_arr, str);
    ft_printab(new_arr, nb_words);
    return (new_arr);
}

下面是主要的btw:

int    main(int ac, char **av)
{
    if (ac != 2) 
        return (print_err("Invalid number of arguments", -1));
    char **new_arr;
    new_arr = ft_split(av[1]);
    free(new_arr);
    return (0);
}

我必须说,如果我不填充或打印数组,我不会得到错误。
当我这样做的时候,数组就像我希望的那样被填充了,但是valgrind给了我很多错误:

==401691== Memcheck, a memory error detector
==401691== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==401691== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==401691== Command: ./cub3d I\ am\ a\ Fish
==401691== 
==401691== Invalid write of size 1
==401691==    at 0x109830: fill_array (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691==    by 0x10999F: ft_split (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691==    by 0x10922A: main (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691==  Address 0x4a9f0c0 is 16 bytes inside an unallocated block of size 4,194,096 in arena "client"
==401691== 
==401691== Invalid write of size 1
==401691==    at 0x109881: fill_array (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691==    by 0x10999F: ft_split (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691==    by 0x10922A: main (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691==  Address 0x4a9f0c1 is 17 bytes inside an unallocated block of size 4,194,096 in arena "client"
==401691== 
==401691== Conditional jump or move depends on uninitialised value(s)
==401691==    at 0x484ED19: strlen (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==401691==    by 0x48EADB0: __vfprintf_internal (vfprintf-internal.c:1517)
==401691==    by 0x48D481E: printf (printf.c:33)
==401691==    by 0x1098EF: ft_printab (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691==    by 0x1099B0: ft_split (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691==    by 0x10922A: main (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691== 
==401691== Conditional jump or move depends on uninitialised value(s)
==401691==    at 0x484ED28: strlen (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==401691==    by 0x48EADB0: __vfprintf_internal (vfprintf-internal.c:1517)
==401691==    by 0x48D481E: printf (printf.c:33)
==401691==    by 0x1098EF: ft_printab (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691==    by 0x1099B0: ft_split (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691==    by 0x10922A: main (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691== 
==401691== Conditional jump or move depends on uninitialised value(s)
==401691==    at 0x48FF7B7: _IO_new_file_xsputn (fileops.c:1218)
==401691==    by 0x48FF7B7: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1196)
==401691==    by 0x48EB08B: outstring_func (vfprintf-internal.c:239)
==401691==    by 0x48EB08B: __vfprintf_internal (vfprintf-internal.c:1517)
==401691==    by 0x48D481E: printf (printf.c:33)
==401691==    by 0x1098EF: ft_printab (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691==    by 0x1099B0: ft_split (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691==    by 0x10922A: main (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691== 
==401691== Syscall param write(buf) points to uninitialised byte(s)
==401691==    at 0x4988A37: write (write.c:26)
==401691==    by 0x48FEF6C: _IO_file_write@@GLIBC_2.2.5 (fileops.c:1180)
==401691==    by 0x4900A60: new_do_write (fileops.c:448)
==401691==    by 0x4900A60: _IO_new_do_write (fileops.c:425)
==401691==    by 0x4900A60: _IO_do_write@@GLIBC_2.2.5 (fileops.c:422)
==401691==    by 0x48FF754: _IO_new_file_xsputn (fileops.c:1243)
==401691==    by 0x48FF754: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1196)
==401691==    by 0x48EA049: outstring_func (vfprintf-internal.c:239)
==401691==    by 0x48EA049: __vfprintf_internal (vfprintf-internal.c:1593)
==401691==    by 0x48D481E: printf (printf.c:33)
==401691==    by 0x1098EF: ft_printab (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691==    by 0x1099B0: ft_split (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691==    by 0x10922A: main (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691==  Address 0x4a9f0ba is 10 bytes inside a block of size 1,024 alloc'd
==401691==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==401691==    by 0x48F2C23: _IO_file_doallocate (filedoalloc.c:101)
==401691==    by 0x4901D5F: _IO_doallocbuf (genops.c:347)
==401691==    by 0x4900FDF: _IO_file_overflow@@GLIBC_2.2.5 (fileops.c:744)
==401691==    by 0x48FF754: _IO_new_file_xsputn (fileops.c:1243)
==401691==    by 0x48FF754: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1196)
==401691==    by 0x48E91CC: outstring_func (vfprintf-internal.c:239)
==401691==    by 0x48E91CC: __vfprintf_internal (vfprintf-internal.c:1263)
==401691==    by 0x48D481E: printf (printf.c:33)
==401691==    by 0x1098EF: ft_printab (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691==    by 0x1099B0: ft_split (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691==    by 0x10922A: main (in /mnt/nfs/homes/hlevi/42/Ghub/Cub3D/cub3d)
==401691== 
arr[0] = |I|
arr[1] = |am|
arr[2] = |a|
arr[3] = |Fish|
==401691== 
==401691== HEAP SUMMARY:
==401691==     in use at exit: 0 bytes in 0 blocks
==401691==   total heap usage: 2 allocs, 2 frees, 1,072 bytes allocated
==401691== 
==401691== All heap blocks were freed -- no leaks are possible
==401691== 
==401691== Use --track-origins=yes to see where uninitialised values come from
==401691== For lists of detected and suppressed errors, rerun with: -s
==401691== ERROR SUMMARY: 36 errors from 6 contexts (suppressed: 0 from 0)

我一定是哪里出了问题,但是我已经试了很多方法,仍然不能成功,有人有什么解决办法吗?

3wabscal

3wabscal1#

好的,谢谢你的回答,我做错的是声明int *arr_byte而不是int8_t*char*
感谢伊恩,衬垫是错的!
现在,该函数运行良好

相关问题