#arrays #c #struct #segmentation-fault #pointer-to-pointer
#массивы #c #структура #ошибка сегментации #указатель на указатель
Вопрос:
Я пытаюсь написать программу, которая считывает текстовый файл в 2D-массив структур, но попытка поместить структуру в этот массив приводит к сбою программы.
Вот программа
ppm.c
#include "ppm.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
image parse_ascii_image(FILE *fp) {
char magic[3];
char comm[1024];
char size[10];
image img;
int height;
int width;
... // some code
pixel **pixelarr;
printf("Commencing internal malloc...n");
if (height <= 1024 amp;amp; width <= 1024 amp;amp; height > 0 amp;amp; width > 0){
pixelarr = (pixel **) malloc(height * sizeof(pixel*));
}else{
fprintf(stderr, "Error: Invalid image size: %d * %d", width, height);
return img;
}
for (int i = 0; i < height; i ){
pixelarr[i] = malloc(width * sizeof(pixel));
}
int d = 0;
int e;
printf("Filling in array:n");
for (int row = 0; row < height; row ){
for (int col = 0; col < width; col ){
for (int i = 0; i < 3; i ){
while ((e = fgetc(fp)) != 'n'){
d = d * 10;
e = e - 60;
d = e;
}
if (i == 0){
pixelarr[row][col].red = d;
}
if (i == 1){
pixelarr[row][col].green = d;
}
if (i == 2){
pixelarr[row][col].blue = d;
}
d = 0;
}
}
}
printf("Finished! Copying pixels over: n");
for (int row = 0; row < height; row ){
for (int col = 0; col < width; col ){
img.pixels[row][col] = pixelarr[row][col];
// ^^^This is where the program crashes
}
}
printf("Finished! Freeing internal malloc:n");
... // some more code
}
соответствующая информация из ppm.h:
#ifndef PPM_H
#define PPM_H 1
#include <stdio.h>
...
typedef struct pixel pixel;
struct pixel {
int red;
int green;
int blue;
};
typedef struct image image;
struct image {
enum ppm_magic magic; // PPM format
char comments[1024]; // All comments truncated to 1023 characters
int width; // image width
int height; // image height
int max_color; // maximum color value
pixel **pixels; // 2D array of pixel structs.
};
...
// Parses an ASCII PPM file.
image parse_ascii_image(FILE *fp);
...
#endif
Если кто-нибудь может помочь мне выяснить, что вызывает сбой моей программы, я был бы признателен.
Спасибо!
Комментарии:
1.
img.pixels
никогда не инициализируется. Кажется , все указывает на то, что вы должны просто заменить эти конечные вложенные циклыimg.pixels = pixelarr;
и НЕ освобождатьpixelarr
их впоследствии. Это касается того, кто принимает возвращаемое изображение. Вы также должны правильно инициализировать все элементыimg
.2. относительно:
enum ppm_magic magic; // PPM format
это объявление экземпляра определенногоenum
типа. Но перечисление никогда не определяется перед использованием3. относительно:
struct pixel { int red; int green; int blue; };
«Цвета» в пикселе составляют 8 бит каждый, а неint
(4 или 8 байт)4. OT: относительно;
pixelarr = (pixel **) malloc(height * sizeof(pixel*));
иpixelarr[i] = malloc(width * sizeof(pixel));
1) содержимоеpixel
неправильно определено. (и вы предполагаете, что пиксель равен 24 битам) 2) возвращаемый типvoid*
— это тот, который может быть присвоен любому указателю. Приведение просто загромождает код и подвержено ошибкам. 3) всегда проверяйте (!= NULL) возвращаемое значение, чтобы убедиться, что операция прошла успешно. Если не удалось (== NULL), сообщите пользователю через:perror( "malloc failed" );
, который выведетstderr
как ваше сообщение об ошибке, так и текстовую системную ошибку.5. относительно:
pixelarr[i] = malloc(width * sizeof(pixel));
строка изображения должна быть кратна 4 (независимо от видимой ширины изображения), поэтому этот оператор может быть недостаточно длинным, чтобы вместить всю строку. из-за вышесказанного this:for (int row = 0; row < height; row ){ for (int col = 0; col < width; col ){
имеет очень хорошие шансы не получить доступ ко всем правильным пикселям
Ответ №1:
Несколько проблем:
1: img.pixels никогда не инициализируется. Каждый раз, когда вы создаете указатель на что-либо, не присваивая ему сначала значение, попробуйте установить для него значение NULL, чтобы упростить отладку. Обратите внимание, что это не решит проблему. Чтобы исправить это, просто инициализируйте их экземпляром struct .
2: Вы должны освободить pixelarr
. Большинство современных ОС делают это, но это все еще очень, очень хорошая практика.
3: Не было бы проще не использовать вложенные циклы, а вместо этого делать img.pixels = pixelarr
? Он достигает того же (если это не для класса, и эта часть обязательна).