EXC_BAD_ACCESS, невозможно найти ошибку - PullRequest
0 голосов
/ 14 июня 2019

Я пытался решить эту проблему в течение достаточно долгого времени, надеюсь, кто-то здесь сможет объяснить, как я смогу справиться с этой проблемой.

Я читал, что это указательуказывая на нераспределенный набор памяти, однако я еще ничего не освободил и не могу найти, где мне не хватает.

Ошибка:

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

У меня естьотлаживал мою ошибку, и она возвращает меня к этой функции:

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] != '\0')
        index++;
        return (index);
}

Grid Generator:

/*
** 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] = '\0';
        while (elem_index < grid_size)
        {
            map[index][elem_index] = '.';
            elem_index++;
        }
        index++;
        elem_index = 0;
    }
    return (map);
}

Весь валгринд:

==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

Ответы [ 2 ]

1 голос
/ 14 июня 2019

Это недопустимое выделение памяти:

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

Было бы достаточно места для grid_size указателей плюс один дополнительный байт, что не имеет смысла.

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 по определению, поэтому умножение на него не имеет никакого эффекта.

Таким образом, даже если код логически неверен, он дает правильные результаты.

1 голос
/ 14 июня 2019
(grid_size * sizeof(*map)) + 1

слишком мало - вам нужно

(grid_size + 1) * sizeof(*map)

Технически, вы должны сделать то же самое с

grid_size * sizeof(char) + 1

, но это работает, потому что sizeof(char) - это единица.

Попробуйте переписать этот код как

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

, чтобы сохранить оба распределения в одной и той же форме.

...