get_pixel function raises bus error: 10

danielgek picture danielgek · Dec 10, 2013 · Viewed 8k times · Source
    #include    <sys/types.h>
    #include    <sys/stat.h>
    #include    <sys/mman.h>    
    #include    <fcntl.h>
    #include    <stdio.h>   
    #include    <stdlib.h>  
    #include    <string.h>  
    #include    <unistd.h>
    #include    <limits.h>  
    #include    <pthread.h>

    #define FILE_MODE   (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

    #ifndef MAP_FILE    /* 44BSD defines this & requires it to mmap files */
    #define MAP_FILE    0   /* to compile under systems other than 44BSD */
    #endif

    #define SIZE 20

    #define N 3

    struct stat statbuf;

    struct pixel
    {
        char R;
        char G;
        char B;
    };

    char * src;
    int size;

    struct pixel *get_pixel(char *buf, int *pos)
    {
        struct pixel pix;
        struct pixel *ppix = &pix;
        ppix->R = buf[*pos];
        ppix->G = buf[(*pos)+1];
        ppix->B = buf[(*pos)+2];
        (*pos) += 3;
        return ppix;
    }

    void write_pixel(struct pixel *ppix, char *buf, int *pos)
    {
        buf[*pos] = ppix->G;
        buf[(*pos)+1] = ppix->B;
        buf[(*pos)+2] = ppix->R;
        (*pos) += 3;
    }

    void * do_rotation(void *rotation)
    {
        int fdout;
        char    *dst;
        char fich[SIZE];

        int counter,index, pos, x, y;
        int xmax = 0;
        int ymax = 0;
        int colormax = 0;

        /* Construção do nome do ficheiro de saída */
        sprintf(fich, "rot%d.ppm", *((int*)rotation));

        /* Zona #2 */

        if ( (fdout = open(fich, O_RDWR | O_CREAT | O_TRUNC,FILE_MODE)) < 0)
        {
            fprintf(stderr,"can't creat %s for writing\n", fich);
            exit(1);
        }

        /* set size of output file */
        if (lseek(fdout, size - 1, SEEK_SET) == -1)
        {
            fprintf(stderr,"lseek error\n");
            exit(1);
        }
        if (write(fdout, "", 1) != 1)
        {
            fprintf(stderr,"write error\n");
            exit(1);
        }


        if ( (dst = mmap(0, size, PROT_READ | PROT_WRITE,MAP_SHARED,fdout, 0)) == (caddr_t) -1)
        {
            fprintf(stderr,"mmap error for output\n");
            exit(1);
        }
        /* Fim da Zona #2 */ 

        sscanf(src,"P6\n%d %d\n%d\n",&xmax,&ymax,&colormax);

        struct pixel imagem [ymax][xmax];

        for (counter=0, index=0; counter<3;index++)
        {
            if (src[index]=='\n')
                ++counter;
        }   
        pos=index-1;
        for (y=0;y<ymax;y++)
            for (x=0;x<xmax;x++)
                imagem[y][x] = *(get_pixel(src,&pos));
        pos=index;

        switch (*((int*)rotation))
        {
            case 0 :
                //Rotação 90º clockwise
                sprintf(dst,"P6\n%d %d\n%d\n",ymax,xmax,colormax);
                for (x=0; x<xmax; x++)
                    for (y=ymax-1; y> -1;y--)
                        write_pixel(&(imagem[y][x]),dst,&pos);
                break;
            case 1:
                //Rotação 180º
                sprintf(dst,"P6\n%d %d\n%d\n",xmax,ymax,colormax);
                for (y=ymax-1;y>-1;y--)
                    for (x = xmax-1; x>-1; x--)
                        write_pixel(&(imagem[y][x]),dst,&pos);
                break;
            case 2:
                //Rotação 270º clockwise
                sprintf(dst,"P6\n%d %d\n%d\n",ymax,xmax,colormax);
                for (x=xmax-1; x>-1; x--)
                    for (y=0; y<ymax;y++)
                        write_pixel(&(imagem[y][x]),dst,&pos);
                break;


        }

    /* Zona #3 */
        munmap(dst,size);
        close(fdout);
    /* Fim da Zona #3 */

        pthread_exit(NULL);

    }

    int get_stat(int fdin)
    {
        struct stat pstatbuf;   
        if (fstat(fdin, &pstatbuf) < 0) /* need size of input file */
        {
            fprintf(stderr,"fstat error\n");
            exit(1);
        }
        return pstatbuf.st_size;
    }


    int main(int argc, char *argv[])
    {
        int id[N];
        int fdin, i;

        if (argc != 2)
        {
            fprintf(stderr,"usage: trab11 <fromfile>\n");
            exit(1);
        }

        if ( (fdin = open(argv[1], O_RDONLY)) < 0)
        {
            fprintf(stderr,"can't open %s for reading\n", argv[2]);
            exit(1);
        }

        size = get_stat(fdin);

    /* Zona # 1*/
        if ( (src = mmap(0, size, PROT_READ, MAP_FILE | MAP_SHARED, fdin, 0)) == (caddr_t) -1)
        {
            fprintf(stderr,"mmap error for input\n");
            exit(1);
        }
    /* Fim da Zona #1 */

    /* Zona #5 */
        pthread_t tid[N];
        for (i=0; i<N; i++){
            id[i]=i;
            pthread_create (&tid[i], NULL, do_rotation, &id[i]);
        }
        for (i=0; i<N; i++)
            pthread_join (tid[i], NULL);
    /* Fim da Zona #5 */

    /* Zona #4 */
        munmap(src,size);
        close(fdin);
    /* Fim da Zona #4 */

        exit(0);
    }

Every time I run this on Mac it gives me Bus error: 10, but if I run it on Linux it doesn't give me any error can someone give me a solution.

PS: The error is on get_pixel function but I still can't figure it out.

Answer

Shafik Yaghmour picture Shafik Yaghmour · Dec 10, 2013

In get_pixel you are returning a pointer to an automatic variable that will not exist when you exit the function here:

return ppix;

This declares an automatic variable:

struct pixel pix;

whose lifetime ends at the end of the function and therefore referring to that memory after you return from get_pixel is undefined behavior.

You can dynamically allocate using malloc:

struct pixel *ppix = malloc( sizeof( struct pixel ) ) ;

but you must remember to call free on the memory when you are done with it.