fgetc () и feof () генерируют segfault с большими файлами - PullRequest
0 голосов
/ 11 октября 2019

Я пытаюсь написать программу, которая манипулирует ppm-файлами изображений, отлично работает с относительно небольшими файлами размером до 622x1023 или около того, но с размером файла программа выдает ошибку segfault.

У меня естьизолировал проблему с этой функцией:

void img2list(FILE *fp,int x,int y,int bd,int *resultado,long tamano){
    int dimx=x,dimy=y;
    int bitDepth=bd;
    long numeroPixeles=(dimx*dimy*bitDepth);
    int con=0;

    int pixels[numeroPixeles];

    while (!feof(fp)){
        pixels[con]=fgetc(fp);
        con++;
    }
    memcpy(resultado,pixels,tamano);
}

специально для:

feof(fp)

и

fgetc(fp)

Я компилирую код с помощью этой команды: gcc main.c -o pim И я запускаю Ubuntu 19.04 на ядре i7 5820k с 16 ГБ ОЗУ

Вот весь код:

#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int * getMeta(FILE *fp){
    static int meta[3];
    size_t len = 0;
    char * line = NULL;
    char delim[] = " ";
    getline(&line,&len,fp);
    getline(&line,&len,fp);

    char *ptr1 = strtok(line, delim);
    char *ptr2 = strtok(NULL, delim);
    sscanf(ptr1, "%d", &meta[0]);
    sscanf(ptr2, "%d", &meta[1]);
    getline(&line,&len,fp);
    char *ptr3 = strtok(line, delim);
    sscanf(ptr3, "%d", &meta[2]);
    return meta;
}

void img2list(FILE *fp,int x,int y,int bd,int *resultado,long tamano){
    int dimx=x,dimy=y;
    int bitDepth=bd;
    long numeroPixeles=(dimx*dimy*bitDepth);
    int con=0;

    int pixels[numeroPixeles];

    while (!feof(fp)){
        pixels[con]=fgetc(fp);
        con++;
    }
    memcpy(resultado,pixels,tamano);
}
void list2file(int *pixeles,int x,int y,int bitDepth, char nombre[]){
    int dimx = x, dimy = y;
    long numeroPixeles = dimx*dimy*bitDepth;
    FILE *archivo = fopen(nombre, "wb"); /* b - binary mode */
    (void) fprintf(archivo, "P6\n%d %d\n255\n", dimx, dimy);
    for(long i=0;i<numeroPixeles;i++){
        (void) fprintf(archivo,"%c",(char)pixeles[i]);
    }
    (void) fprintf(archivo,"\n");
    (void) fclose(archivo);
}

int main(void){
    int *meta;
    int values,dimx,dimy;
    int bitDepth=3;
    FILE *fp = fopen("test.ppm","rb");
    meta=getMeta(fp); // Dimenciones de la imagen

    dimx = meta[0];
    dimy = meta[1];
    values = meta[2];

    printf("dimencion en x: %d\n",dimx);
    printf("dimencion en y: %d\n",dimy);
    printf("cantidad de valores por pixel: %d\n",values);
    long tamano=(dimx*dimy*bitDepth*sizeof(int));
    int *pixeles=malloc(tamano);
    img2list(fp,dimx,dimy,3,pixeles,tamano);

    char nombre[]="pena.ppm";
    list2file(pixeles,dimx,dimy,bitDepth,nombre);


    (void) fclose(fp);
    return EXIT_SUCCESS;
}

Спасибо.

1 Ответ

2 голосов
/ 11 октября 2019

Это:

int pixels[numeroPixeles];

- это переполнение стека , если numeroPixeles не ограничен небольшой константой. Выделение больших объектов в стеке не позволяет отличить успех / неудачу;ваша программа просто взрывается (и, возможно, приводит к выполнению кода под контролем того, кто является автором данных, которые вы обрабатываете). Для работы с данными произвольного размера вам понадобится malloc, где вы можете проверить успешность.

...