Не выделяется память, точнее не могу к ней обратиться
есть такая функция
void field_malloc(int ***field, ErrorCode_t *error_code) {
*field = (int **)malloc(sizeof(int *) * FIELD_HEIGHT +
sizeof(int) * FIELD_HEIGHT * FIELD_WIDTH);
int *ptr = (int *)(*field + FIELD_HEIGHT);
for (int i = 0; i < FIELD_HEIGHT && error_code == Ok; i++) {
(*field)[i] = ptr + FIELD_WIDTH * i;
}
}
в другом файле пытаюсь её использовать, но падает segmentation fault
GameInfo_t tetris_gameinfo = {0};
ErrorCode_t error_code = Ok;
// tetris_gameinfo.field = (int **)malloc(
// sizeof(int *) * FIELD_HEIGHT + sizeof(int) * FIELD_HEIGHT *
// FIELD_WIDTH);
// int *ptr = (int *)(tetris_gameinfo.field + FIELD_HEIGHT);
// for (int i = 0; i < FIELD_HEIGHT && error_code == Ok; i++) {
// tetris_gameinfo.field[i] = ptr + FIELD_WIDTH * i;
// }
field_malloc(&(tetris_gameinfo.field), &error_code);
tetris_gameinfo.field[0][0] = 5;
проверял на NULL, говорит что там что-то есть, но обратиться к памяти не могу
Если использовать кусок кода, который закомментирован, то обращаться могу и сегфолтов нет
Большой провал в знаниях по инициализации структур, их указателей(..
Еще есть такой вариант функции
int **field_malloc(ErrorCode_t *error_code) {
int **field = (int **)malloc(sizeof(int *) * FIELD_HEIGHT +
sizeof(int) * FIELD_HEIGHT * FIELD_WIDTH);
int *ptr = (int *)(field + FIELD_HEIGHT);
for (int i = 0; i < FIELD_HEIGHT && error_code == Ok; i++) {
field[i] = ptr + FIELD_WIDTH * i;
}
return field;
}
не понятно как оно работать должно, вроде область памяти возвращаю, но код тоже с ней не пашет, хотя у знакомого на компе всё работает
Буду благодарен за ресурс где рассматриваются подобные случаи, в частности структуры, их инициализация, как у них устроена работа с памятью
Ответы (1 шт):
error_code == Ok -> *error_code == Ok.
Иначе вы сравниваете указатель с числовым значением. Это всегда ложь, цикл не выполняется, указатели не устанавливаются.
P.S. Компилятор у меня выдаёт предупреждение/ошибку если #define Ok 1. Как я понял, в вашем коде Ok равно нулю. Указатели можно сравнивать с целым нулём, предупреждения не будет.
$ gcc temp.c temp.c: In function ‘field_malloc’: temp.c:22:50: warning: comparison between pointer and integer 22 | for (int i = 0; i < FIELD_HEIGHT && error_code == Ok; i++) { | ^~ $ gcc -std=c11 -pedantic -Wall -Wextra -Werror -Wwrite-strings -Wconversion temp.c temp.c: In function ‘field_malloc’: temp.c:22:50: error: comparison between pointer and integer [-Werror] 22 | for (int i = 0; i < FIELD_HEIGHT && error_code == Ok; i++) { | ^~ cc1: all warnings being treated as errors
P.P.S. Используйте отладчик. Собрал, запустил, убедился что программа в цикл не заходит:
$ gcc -g temp.c temp.c: In function ‘field_malloc’: temp.c:22:50: warning: comparison between pointer and integer 22 | for (int i = 0; i < FIELD_HEIGHT && error_code == Ok; i++) { | ^~ $ gdb ./a.out GNU gdb (Debian 13.1-3) 13.1 Copyright (C) 2023 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <https://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from ./a.out... @(gdb) b main Breakpoint 1 at 0x11c5: file temp.c, line 32. @(gdb) run Starting program: /home/sv/desk/stackoverflow/a.out [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Breakpoint 1, main () at temp.c:32 32 GameInfo_t tetris_gameinfo = {0}; @(gdb) n 33 ErrorCode_t ec = Ok; @(gdb) n 34 field_malloc(&(tetris_gameinfo.field), &ec); @(gdb) s field_malloc (field=0x7fffffffdf78, error_code=0x7fffffffdf74) at temp.c:17 17 *field = (int **)malloc(sizeof(int *) * FIELD_HEIGHT + @(gdb) n 20 int *ptr = (int *)(*field + FIELD_HEIGHT); @(gdb) n 22 for (int i = 0; i < FIELD_HEIGHT && error_code == Ok; i++) { @(gdb) n 25 }
P.P.P.S Используйте valgrind или аналог. Он сразу говорит, что указатели в буфере не заполнены:
$ gcc -g temp.c temp.c: In function ‘field_malloc’: temp.c:22:50: warning: comparison between pointer and integer 22 | for (int i = 0; i < FIELD_HEIGHT && error_code == Ok; i++) { | ^~ $ valgrind ./a.out ==62285== Memcheck, a memory error detector ==62285== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==62285== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info ==62285== Command: ./a.out ==62285== ==62285== Use of uninitialised value of size 8 ==62285== at 0x1091EE: main (temp.c:35) ==62285== ==62285== Invalid write of size 4 ==62285== at 0x1091EE: main (temp.c:35) ==62285== Address 0x0 is not stack'd, malloc'd or (recently) free'd ...
P.P.P.P.S Размещая в одном буфере указатели и целые вы играете с огнём. На большинстве компиляторов это сработает, но это неопределённое поведение из-за выравнивания для целых.