1

Я пытаюсь взять файл bmp и сделать полутоновую копию. Я изучаю динамическое распределение, и мне приходится динамически выделять 2D-массив, в который я импортирую BMP-файл и манипулирую им, поэтому он будет работать с различными размерами изображения. Но ближе к концу (я обозначил, где) я получаю Seg Fault, и я понятия не имею, почему. Все отлично работает, если я не динамически выделяю «пиксели».c - ошибка сегментации, назначаемая массиву 2d

#include <stdio.h> 
#include <stdlib.h>  

int main(void) { 

    const int HEADER_SIZE = 54; 

    FILE *infile = fopen("test1.bmp", "rb"); 
    FILE *outfile1 = fopen("copy1.bmp", "wb"); 

    int i, width, height, r, c, bmpsize; 
    char header[HEADER_SIZE], filename[32]; 
    char **pixels;        //initialize pixels here 

    puts("Enter the filename: "); 

    i = -1; 
    while(filename[i] != '\n') 
    { 
     i++; 
     scanf("%c", &filename[i]); 
    } 
    filename[i] = '.'; 
    filename[i+1] = 'b'; 
    filename[i+2] = 'm'; 
    filename[i+3] = 'p'; 
    filename[i+4] = '\0'; 

    i = -1; 
    while(filename[i] != '\0') 
    { 
     i++; 
     printf("%c", filename[i]); 
    } 

    infile = fopen(filename, "rb"); 

    puts("Enter the height and width (in pixels): "); 
    scanf("%d%d", &height, &width); 

    bmpsize = 3 * width * height; 

    pixels = malloc(height * sizeof(char*));   //DA part 1 

    for(i = 0; i < height; i++) 
    { 
     pixels[i] = malloc((width * 3) * sizeof(char)); //DA part 2 
    } 

    fread(header, 1 , HEADER_SIZE, infile); 
    fread(pixels, 1 , bmpsize, infile); 

    for(r = 0; r < height; r++) { 
     for (c = 0; c < width*3; c += 3) { 
      int avg= 0; 
      puts("THIS PUTS PRINTS: THE NEXT LINE IS MY PROBLEM"); 
      avg = ((int) pixels[r][c] + (int) pixels[r][c+1] + (int) pixels[r][c+2])/3;//This is my problem line, why? 
      puts("THIS PUTS DOESN'T PRINT. ERROR: SEG. FAULT(core dumped)"); 
      pixels[r][c] = (char) avg; 
      pixels[r][c+1] = (char) avg; 
      pixels[r][c+2] = (char) avg; 
     } 
    } 

    puts("Done. Check the generated images."); 

    fwrite(header, sizeof(char) , HEADER_SIZE, outfile1); 
    fwrite(pixels, sizeof(char) , bmpsize, outfile1); 

    fclose(infile); 
    fclose(outfile1); 
    return 0; 
} 
+0

Лучше всего добавить тег C для вопроса C – mathematician1975

+0

, независимо от проблемы, вы все равно должны проверить, что вы не получаете указатели NULL, возвращаемые malloc. Выделение указателя NULL также даст вам segfault. – user1514631

+0

Do 'char (* pixels) [width * 3] = malloc (width * height * 3);', тогда вы можете использовать 'pixels [r] [c]', а также 'fread'. BTW проверяет возвращаемое значение 'fread' и' malloc'. –

ответ

1

Я думаю, что проблема с fread вызова и как вы настраиваете входной буфер для содержимого файла

pixels = malloc(height * sizeof(char*));   //DA part 1 

for(i = 0; i < height; i++) 
{ 
    pixels[i] = malloc((width * 3) * sizeof(char)); //DA part 2 
} 

fread(pixels, 1 , bmpsize, infile); 

Память, которую выделили в общей составляет bmpsize байт но длина pixels - это всего лишь height байтов - и все же вы передаете ее fread, как если бы это был буфер длиной bmpsize. Каждый элемент в pixels является char* - каждый из них представляет собой блок динамически распределенного массива, но это не означает, что вы можете обрабатывать массив pixels как непрерывный блок памяти.

Эти массивы, распределенные динамически в ваших циклах, поэтому не инициализируются, что может привести к segfaults, когда вы читаете их позже в своем цикле (чтение неинициализированных переменных является неопределенным поведением).

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

+0

, но 'c' должен работать до' width * 3-3', а не 'width * 3-1' – user1514631

+0

Я имел в виду' c' не будет ширины * 3-1 в последней итерации, как вы предлагаете, но ширина * 3 -3 – user1514631

+0

Я думаю, что вы здесь. Как я настраивал свой malloc() Я не получал непрерывной памяти, и я считаю, что предмет fread() требует смежного блока памяти. Поэтому я смоделировал свой 2D-массив, используя пиксели 1D Array [r * height + c]. (r * height перескакивает меня вперед до блока соответствующей строки, а + c возвращает меня в нужное место в этой строке. К сожалению, по какой-то причине это делает изображение не изменяющимся для первых 3/4 изображения. эй, по крайней мере, это уже не сегрегация. Так спасибо. – David

0

Ответ mathematician1975 почти правильно, так как вы доступ к данным из-за пределов области вы выделяемой, но последний индекс c во внутреннем цикле не 3*width-1 ни 3*width-3, но на самом деле это width*3.

Вы должны адаптировать внутренний цикл к:

for (c = 0; c < width*3-3; c += 3) 

Таким образом c будет продолжаться до тех пор, width*3-3, а затем вы можете сделать c, c+1 и c+2 и вы побываете последние байты линий с c+2.

+0

Спасибо за помощь, но я не думаю, что это проблема.Представьте себе, что ширина равна 2, тогда (ширина * 3) дает нам 6 индексов: 0, 1, 2, 3, 4, 5. Это составляет цикл (c = 0; c <6; c + = 3) { так первая итерация c равна 0, и я получаю доступ к 0, 1, 2 . Вторая итерация c равна 3, и я получаю доступ к 3, 4, 5 , а следующая итерация c - 6, и мы выходим из цикла правильно. Но спасибо за попытку, я вот здесь воткнулся с этой ошибкой. :-) – David

Смежные вопросы