Получение очень раздражающей ошибки сегментации ... неправильный массив 2d в C - PullRequest
2 голосов
/ 30 сентября 2010

У меня небольшая проблема с этим.Прежде всего, это для простой графической библиотеки, которую я писал.

То, что я делаю, позволяет мне объявить несколько «виртуальных экранов» с размерами по выбору программиста.Для этого мне нужно динамически выделить достаточно памяти на основе количества пикселей, которое будет содержать экран.

Кажется, что функция, которая выделяет эту память, работает в моей программе только один раз, а затем завершается сбоем (с ошибкой)в другой раз я это называю.Я думаю, что проблема может быть в том, как я обхожу виртуальный экран (screen_t).Я реализовал это так, что функция new_screen возвращает не указатель, а сам экран.Я думаю, может быть, это было ошибкой.Кроме того, когда функции, такой как set_current_screen, требуется экран в качестве одного из аргументов, ей передается адрес, например:

set_current_screen(&screen_variable);

Это правильный путь?Это то, что вызывает segfault, когда я звоню new_screen?

Заранее спасибо.Код представляет собой заголовочный файл (очень неполный), и AC-файл, который рисует некоторые фрагменты на одном экране, пытается создать другой, получает ошибку сегмента.Вот они:

хгл.ч

main.c

Ответы [ 3 ]

3 голосов
/ 30 сентября 2010

Прежде всего, ваш код не SEGFAULT'а во втором вызове new_screen (). Вы вводите всех нас в заблуждение :) Сбой кода при попытке получить к нему доступ. Ваша главная проблема заключается в этой строке:

 47     vscreen.bitmap[i] = malloc(height * sizeof(int));

Поскольку вы выделили указатель на массив структурных пикселей, почему вы получаете размер типа int. Вы должны изменить его на следующее:

vscreen.bitmap[i] = malloc(height * sizeof(struct pixel));

Тогда все должно быть в порядке. Но ...

.. В коде также много других проблем. В new_screen вы выделяете массив указателей, а затем каждый ряд отдельно. Почему бы не выделить весь экран сразу?

Сначала вы можете определить растровое изображение как, struct pixel * bitmap; И выделить место для структуры как bitmap = malloc (ширина * высота * sizeof (структура пикселя));

Затем вы можете получить доступ к пикселю в точке (x, y) как растровое изображение [y * WIDTH + x]. Вы также можете скрыть это в функции.

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

Еще одно замечание об использовании циклов. Вы знаете, для этого есть петля: для. Это имеет больше смысла для использования в ваших случаях в коде.

1 голос
/ 30 сентября 2010

Итак, у вас есть:

typedef struct pixel{
    unsigned char b;
    unsigned char g;
    unsigned char r;
    float a;
};

struct virtual_screen{
    int layer;
    int width;
    int height;
    int opacity;
    struct pixel **bitmap;
};

typedef struct virtual_screen screen_t;

Но когда вы собираетесь выделить bitmap член screen_t, вы делаете:

vscreen.bitmap=malloc(width * sizeof(unsigned int *));

Откуда взялось unsigned int*? bitmap имеет тип struct pixel**.

Чтобы избежать подобных ошибок, лучше сделать:

vscreen.bitmap=malloc(width * sizeof *vscreen.bitmap);

И точно так же, когда вы выделяете элементы vscreen.bitmap, вы должны сделать:

vscreen.bitmap[i] = malloc(height * sizeof *vscreen.bitmap[i]);

(Кроме того, вы должны проверить, что malloc удалось!)

В качестве примечания я скажу, что ваша схема размещения немного необычна: вы выделяете по столбцам, но обычно изображения хранятся по строкам. Я понимаю, что вы делаете это, поэтому вы можете использовать координаты (x, y) для индексов массива, но IMO лучше не бороться с соглашением матрицы (строка, столбец).

0 голосов
/ 30 сентября 2010

Проблема заключается в объявлении растрового изображения в структуре virtual_screen.

Попробуйте это:

растровое пиксельное изображение структуры [] [];

Затем исправьте части кода, на которые может повлиять это изменение.

...