EXC_BAD_ACCESS,无法定位错误

EXC_BAD_ACCESS, unable to locate the error

我已经尝试解决这个问题很长一段时间了,希望这里有人能够解释我将如何处理这个问题。

我读到它是一个指向未分配内存集的指针,但是我还没有释放任何东西,也无法找到我缺少的地方。

错误:

Exception: EXC_BAD_ACCESS (code=2, address=0x7fff50fefff8)

我一直在调试我的错误,它 returns 我使用这个函数:

int         check_tetrimino(char **grid, t_tetrimino curr, int ind_y, int ind_x)
{
    int y;
    int x;
    int size;

    size = ft_strlen(grid[0]); // <----- points to this exact line
    x = 0;
    y = 0;
    while (x < 4)
    {
        if (ind_y + curr.y[y] >= size)
            return (-1);
        if (grid[ind_y + curr.y[y]][ind_x + curr.x[x]] != '.')
            return (0);
        x++;
        y++;
    }
    //printf("%c fit on y:%d, x:%d.\n", curr.letter, ind_y, ind_x);
    return (add_to_grid(grid, curr, ind_y, ind_x));
}

这是递归函数调用check_tetrimino

int         check_all_tetr(char **grid, t_tetrimino *curr, int ind_y, int ind_x)
{
    static int tries = 0;
    int size;
    int check_ret;

    size = ft_strlen(grid[0]);
    check_ret = check_tetrimino(grid, *curr, ind_y, ind_x);
    if (check_ret == 0) {
        (ind_x < (size - 1)) ? ++ind_x : ++ind_y && (ind_x = 0);
    }
    if (check_ret == 1)
    {
        if (!(curr->next->letter > 'A' && curr->next->letter < 'Z'))
            return (1);
        assign_curr(&curr, &ind_y, &ind_x);
    }
    if (check_ret == -1)
    {
        if (curr->prev == NULL)
        {
            delete_from_grid(grid, *curr);
            return (-1);
        }
        curr = curr->prev != NULL ? curr->prev : curr;
        delete_from_grid(grid, *curr);
        return (ind_x < (size - 1) ?
                check_all_tetr(grid, curr, curr->grid_y, curr->grid_x + 1) :
                check_all_tetr(grid, curr, curr->grid_y + 1, 0));
    }
    return (check_all_tetr(grid, curr, ind_y, ind_x));
}

这是我的 ft_strlen:

size_t      ft_strlen(const char *s)
{
    size_t index;

    index = 0;
    while (s[index] != '[=14=]')
        index++;
        return (index);
}

网格生成器:

/*
** Genererates a 2D Array performing as a grid
** the size of the grid is based on the amount of tetrimino's
** possible minimum required elements is = √ ⋅ 4
** @param size
** @param size_elem
** @return
*/

char        **ft_grid_gen(size_t size)
{
    char    **map;
    int     index;
    int     elem_index;
    int     grid_size;

    index = 0;
    elem_index = 0;
    grid_size = ft_calc_sqrt(size);
    map = malloc((grid_size * sizeof(*map)) + 1);
    map[grid_size] = NULL;
    while (index < grid_size)
    {
        map[index] = malloc(grid_size * sizeof(char) + 1);
        map[index][grid_size] = '[=15=]';
        while (elem_index < grid_size)
        {
            map[index][elem_index] = '.';
            elem_index++;
        }
        index++;
        elem_index = 0;
    }
    return (map);
}

整个 valgrind:

==7641== Memcheck, a memory error detector
==7641== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==7641== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==7641== Command: ./fillit valid_19
==7641== 
==7641== Conditional jump or move depends on uninitialised value(s)
==7641==    at 0x100001E2F: ft_strlen (in ./fillit)
==7641==    by 0x10000110D: ft_validator (validator.c:29)
==7641==    by 0x100001339: ft_sort_list (sort_list.c:35)
==7641==    by 0x100000F75: main (main.c:41)
==7641== 
==7641== Conditional jump or move depends on uninitialised value(s)
==7641==    at 0x100001367: ft_sort_list (sort_list.c:37)
==7641==    by 0x100000F75: main (main.c:41)
==7641== 
==7641== Invalid read of size 1
==7641==    at 0x100001E28: ft_strlen (in ./fillit)
==7641==    by 0x10000110D: ft_validator (validator.c:29)
==7641==    by 0x100001339: ft_sort_list (sort_list.c:35)
==7641==    by 0x100000F75: main (main.c:41)
==7641==  Address 0x100b58d95 is 0 bytes after a block of size 21 alloc'd
==7641==    at 0x1000991E6: malloc (in /Users/dvan-boc/.brew/Cellar/valgrind/3.14.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==7641==    by 0x100001070: ft_read (reader.c:43)
==7641==    by 0x100000F63: main (main.c:40)
==7641== 
==7641== Invalid read of size 1
==7641==    at 0x100001360: ft_sort_list (sort_list.c:37)
==7641==    by 0x100000F75: main (main.c:41)
==7641==  Address 0x100b58d95 is 0 bytes after a block of size 21 alloc'd
==7641==    at 0x1000991E6: malloc (in /Users/dvan-boc/.brew/Cellar/valgrind/3.14.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==7641==    by 0x100001070: ft_read (reader.c:43)
==7641==    by 0x100000F63: main (main.c:40)
==7641== 
==7641== Conditional jump or move depends on uninitialised value(s)
==7641==    at 0x100001873: subtract_coordinates (solver.c:171)
==7641==    by 0x1000017C6: ft_solve (solver.c:45)
==7641==    by 0x100000FBA: main (main.c:49)
==7641== 
==7641== Conditional jump or move depends on uninitialised value(s)
==7641==    at 0x100001873: subtract_coordinates (solver.c:171)
==7641==    by 0x100001959: subtract_coordinates (solver.c:190)
==7641==    by 0x1000017C6: ft_solve (solver.c:45)
==7641==    by 0x100000FBA: main (main.c:49)
==7641== 
==7641== 
==7641== Process terminating with default action of signal 11 (SIGSEGV)
==7641==  Access not within mapped region at address 0x10408EFB8
==7641==    at 0x100001C31: check_tetrimino (solver.c:134)
==7641==  If you believe this happened as a result of a stack
==7641==  overflow in your program's main thread (unlikely but
==7641==  possible), you can try to increase the size of the
==7641==  main thread stack using the --main-stacksize= flag.
==7641==  The main thread stack size used in this run was 8388608.
==7641== 
==7641== HEAP SUMMARY:
==7641==     in use at exit: 18,978 bytes in 177 blocks
==7641==   total heap usage: 202 allocs, 25 frees, 25,458 bytes allocated
==7641== 
==7641== 72 bytes in 3 blocks are possibly lost in loss record 29 of 47
==7641==    at 0x10009984A: calloc (in /Users/dvan-boc/.brew/Cellar/valgrind/3.14.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==7641==    by 0x1005B2846: map_images_nolock (in /usr/lib/libobjc.A.dylib)
==7641==    by 0x1005C5FE8: objc_object::sidetable_retainCount() (in /usr/lib/libobjc.A.dylib)
==7641==    by 0x10000903B: dyld::notifyBatchPartial(dyld_image_states, bool, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*), bool, bool) (in /usr/lib/dyld)
==7641==    by 0x100009255: dyld::registerObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) (in /usr/lib/dyld)
==7641==    by 0x10020000A: _dyld_objc_notify_register (in /usr/lib/system/libdyld.dylib)
==7641==    by 0x1005B2074: _objc_init (in /usr/lib/libobjc.A.dylib)
==7641==    by 0x10019368D: _os_object_init (in /usr/lib/system/libdispatch.dylib)
==7641==    by 0x10019363A: libdispatch_init (in /usr/lib/system/libdispatch.dylib)
==7641==    by 0x1000A79D5: libSystem_initializer (in /usr/lib/libSystem.B.dylib)
==7641==    by 0x100019A1A: ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==7641==    by 0x100019C1D: ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==7641== 
==7641== LEAK SUMMARY:
==7641==    definitely lost: 0 bytes in 0 blocks
==7641==    indirectly lost: 0 bytes in 0 blocks
==7641==      possibly lost: 72 bytes in 3 blocks
==7641==    still reachable: 1,146 bytes in 24 blocks
==7641==         suppressed: 17,760 bytes in 150 blocks
==7641== Reachable blocks (those to which a pointer was found) are not shown.
==7641== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==7641== 
==7641== For counts of detected and suppressed errors, rerun with: -v
==7641== Use --track-origins=yes to see where uninitialised values come from
==7641== ERROR SUMMARY: 21 errors from 7 contexts (suppressed: 12 from 12)

调试器图片: https://imgur.com/a/53LXvmv

(grid_size * sizeof(*map)) + 1

太小了——你需要

(grid_size + 1) * sizeof(*map)

从技术上讲,您应该对

做同样的事情
grid_size * sizeof(char) + 1

但它成功了,因为 sizeof(char) 是一个。

考虑将那个重写为

(grid_size + 1) * sizeof(*map[index])

保持两种分配形式相同。

这是一个无效的内存分配:

map = malloc((grid_size * sizeof(*map)) + 1);

它将为 grid_size 个指针提供足够的 space 加上一个额外的字节,这没有意义。

map[grid_size] = NULL;

此处您试图存储一个已分配数组的最后一个元素之后的值。唯一可行的方法是指针在您的平台上只有一个字节大(提示:它们不是)。

修复:

map = malloc((grid_size + 1) * sizeof(*map));

这一行出现同样的问题:

    map[index] = malloc(grid_size * sizeof(char) + 1);

逻辑上应该是(grid_size + 1) * sizeof (char)。但是,根据定义,sizeof (char)1,因此您可以摆脱困境,因此乘以它没有任何效果。

所以即使代码在逻辑上是错误的,它也会产生正确的结果。