我已经尝试解决这个问题已有一段时间了,希望这里的人能够解释我将如何处理此问题。
我已经读到它是一个指向未分配的内存集的指针,但是我还没有释放任何东西,也无法找到我所缺少的地方。
错误:
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);
}
网格生成器:
/*
** 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);
}
整个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
答案 0 :(得分:1)
(grid_size * sizeof(*map)) + 1
太小–您需要
(grid_size + 1) * sizeof(*map)
从技术上讲,您应该对
进行相同操作grid_size * sizeof(char) + 1
但是可以解决,因为sizeof(char)
是一个。
考虑将其改写为
(grid_size + 1) * sizeof(*map[index])
使两个分配保持相同的形式。
答案 1 :(得分:1)
这是无效的内存分配:
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
而被保释,因此乘以它没有任何作用。
因此,即使代码在逻辑上是错误的,它也会产生正确的结果。