This is in a program meant to work with ppm image files.
I'm getting a segmentation fault when trying to read an image from a file and assigning that image to my global struct image.
These are the relevant parts of my ppmIO.c file:
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <ppmIO.h>
struct Image *instance;
void ImageRead(char *filename)
{
printf("hi 0!");
int width, height, num, size;
//unsigned char *p;
//Image *image = (Image *) malloc(sizeof(Image));
FILE *fp = fopen(filename, "r");
//if (!image) die("cannot allocate memory for new image");
if (!fp) die("cannot open file for reading");
readPPMHeader(fp, &width, &height);
size = width * height * 3;
printf("hi!");
//instance->data = (unsigned char *) malloc(size);
printf("hi 2!");
instance->width = width;
printf("hi 3!");
instance->height = height;
printf("hi 4!");
if (!instance->data) die("cannot allocate memory for new image");
num = fread((void *) instance->data, 1, (size_t) size, fp);
if (num != size) die("cannot read image data from file");
fclose(fp);
}
This is my ppmIO.h file:
#ifndef PPMIO_H
#define PPMIO_H
struct Image
{
int width;
int height;
unsigned char *data;
};
extern struct Image *instance;
//extern Image *ImageCreate(int width, int height);
//extern void ImageClear(struct Image *image, unsigned char red, unsigned char green, unsigned char blue);
extern void ImageRead(char *filename);
extern void ImageWrite(char *filename);
extern void ImageSetPixel(int x, int y, int chan, unsigned char val);
extern unsigned char ImageGetPixel(int x, int y, int chan);
#endif /* PPMIO_H */
And this is the segmentation fault that GDB reports:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400fff in ImageRead (filename=0x7fffffffdc32 "nika.ppm")
at ppmIO.c:126
126 instance->width = width;
I think there is a problem with how I'm trying to use the Image *instance... but I really have no real clue what is causing this mess. :(
You're getting this error as you have not allocated any memory for instance. Before you try and use any member of instance (i.e. width or data) you must allocate memory (from inside a function), i.e:
instance = malloc(sizeof *instance);
You should not cast the return value of instance (See: this), and there is no need to specify the type since the compiler already knows. You can't allocate the memory when you declare the variable as static initializations must be to constant values (See: this) (the return value of a function is not constant).
You will also need to allocate memory for the instance->data part of the structure, based on the size you read from the file.
Related
This is in a program meant to work with ppm image files.
I'm getting a compilation error when trying to modify a struct and then writing it to a new file.
This is the global struct (declared in ppmIO.c and ppmIO.h):
ppmIO.c:
struct Image *instance;
ppmIO.h:
struct Image
{
int width;
int height;
unsigned char *data;
};
extern struct Image *instance;
This is my imageManip.h file:
#include <ppmIO.h>
void ImageInvert(struct Image **toInvert);
void ImageSwap(struct Image **toSwap);
These are the relevant parts of my imageManip.c file:
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <ppmIO.h>
#include <imageManip.h>
void ImageInvert(struct Image **toInvert) {
int i;
int pix = (*toInvert->width) * (*toInvert->height);
*toInvert = realloc(*toInvert, 2* sizeof *instance);
for (i = 0; i < pix; i++)
{
*(toInvert)->data = ((unsigned char)255 - *(toInvert)->data));
*(toInvert)->data = ((unsigned char)255 - *(toInvert)->data++));
*(toInvert)->data = ((unsigned char)255 - *(toInvert)->data++));
}
}
void ImageSwap(struct Image **toSwap) {
int i;
int pix = (*toSwap)->width * (*toSwap)->height;
*toSwap = realloc(*toSwap, 2* sizeof *instance);
unsigned char what = (*toSwap)->data;
for (i = 0; i < pix-1; i++)
{
(*toSwap)->data = (*toSwap)->data++;
(*toSwap)->data = (*toSwap)->data++;
(*toSwap)->data = what;
what = (*toSwap)->data++;
}
}
This is the ImageWrite method, used to write the modified image structure to a file:
void ImageWrite(char *filename)
{
int num;
printf("%d", num);
int size = (instance->width) * (instance->height) * 3;
FILE *fp = fopen(filename, "w");
if (!fp) die("cannot open file for writing\n");
fprintf(fp, "P6\n%d %d\n%d\n", instance->width, instance->height, 255);
num = fwrite((void *) instance->data, 1, (size_t) size, fp);
if (num != size) die("cannot write image data to file\n");
fclose(fp);
}
This is how I call my modifying functions from main:
ImageInvert(&instance);
ImageSwap(&instance);
ImageWrite(first); //where first is a filename
This is the segmentation fault that gdb reports:
Program received signal SIGSEGV, Segmentation fault.
__mempcpy_sse2 () at ../sysdeps/x86_64/memcpy.S:166
166 ../sysdeps/x86_64/memcpy.S: No such file or directory.
Someone suggested that in my modifying funtions (ImageInvert and ImageSwap), I keep changing the pointer, not the data pointed at. If that is the case, how can I change the data pointed at instead of just the pointer?
As noted in comments to a previous question, the code for ImageInvert() can be made much simpler.
Using subscript notation:
void ImageInvert(struct Image **toInvert)
{
struct Image *image = *toInvert;
int n_colour_vals = (image->width * image->height) * 3;
unsigned char *data = image->data;
for (int i = 0; i < n_colour_vals; i++)
data[i] = 255 - data[i];
}
Using pointers:
void ImageInvert(struct Image **toInvert)
{
struct Image *image = *toInvert;
unsigned char *data = image->data;
unsigned char *end = data + (image->width * image->height) * 3;
while (data < end)
{
*data = 255 - *data;
data++;
}
}
Equivalent changes can probably be made to imageSwap(), though I am not entirely sure what it is supposed to be doing. There were problems in the previous question that might have suggested that the reallocation was a good idea, but (at least for ImageInvert()), that really isn't needed.
I am attempting to write a program to invert the color of an image. My problem is when I try to read from the DIB header in my BMP file.
When I try to get the file header size and use fread(dib.fileheader, 4,1,fp); . I get an error that says "The memory could not be written". I have attached it for further clarification.
Here is my code:
#include <stdio.h>
#include <string.h>
struct BMP {
char filetype[2]; // must be BM, must check if BM
unsigned int filesize;
short reserved1;
short reserved2;
unsigned int dataoffset;
};
struct DIB {
unsigned int fileheader;
unsigned int headersize;
int width;
int height;
short planes;
short bitsperpixel; /* we only support the value 24 here */
unsigned int compression; /* we do not support compression */
unsigned int bitmapsize;
int horizontalres;
int verticalres;
unsigned int numcolors;
unsigned int importantcolors
};
struct pixel {
int val;
char * def;
struct listitem * next;
};
void invertImage(char fileName[]){
struct BMP bmp;
struct DIB dib;
FILE *fp = fopen(fileName, "rb");
//FileType
fread(bmp.filetype, 1,2,fp);
printf("Value is %c\n", bmp.filetype[1]);
//Check if file format is BM
if(bmp.filetype[0] != 'B' && bmp.filetype[1] !='M'){
printf("Wrong format");
}
//Size of the file in bytes
fread(bmp.filesize, 4,1,fp);
printf("Value is %d\n", bmp.filesize);
//Go to dataoffset
fseek(fp,10,SEEK_CUR);
fread(bmp.dataoffset, 4,1,fp);
printf("Offset is %d\n", bmp.dataoffset);
fread(dib.fileheader, 4,1,fp);
printf("File header is %d bytes\n", dib.fileheader);
fclose(fp);
}
int main(int argc, char *argv[] ){
printf("Program name %s\n", argv[0]);
if( strcmp(argv[1],"-invert") == 0) {
printf("Invert\n");
printf("File name is %s\n", argv[2] );
invertImage(argv[2]);
}
else {
printf("Greyscale\n");
//greyScaleImage();
}
return 0;
}
Also here is the output to my program.
fread expects a pointer to memory to write the file contents. So you need to give it the address of dib.fileheader
fread( &dib.fileheader, sizeof(dib.fileheader),1,fp );
printf("File header is %d bytes\n", dib.fileheader);
It's complaining because it's interpreting whatever is in dib.fileheader as the address to write to, which may or may not be valid for your program.
Note that the following is ok as it stands because bmp.filetype is already a pointer to char - it's a char[]
fread(bmp.filetype, 1,2,fp);
printf("Value is %c\n", bmp.filetype[1]);
To make it a bit more general, you could write
fread(bmp.filetype, sizeof(bmp.filetype), 1, fp);
printf("Value is %c\n", bmp.filetype[1]);
I tried to compile your code. You must make some change in your code.
fread(bmp.filesize, 4,1,fp); --- > fread(&bmp.filesize, 4,1,fp);
fread(bmp.dataoffset, 4,1,fp); --- > fread(&bmp.dataoffset, 4,1,fp);
fread(dib.fileheader, 4,1,fp); --- > fread(&dib.fileheader, 4,1,fp);
declare the function : void invertImage(char fileName[]);
I was writing a C program that reads the width and heights of a bmp image following (http://smsoftdev-solutions.blogspot.com.au/2014/07/code-for-reading-bmp-image-files.html). But I've met an error in terminal, it shows that:
i './a.out' terminated by signal SIGSEGV (Address boundary error)
I did some googling, they mention it's accessing extra memory problem, but I can't really find that in my code, any suggestion would be appreciated
#include <stdio.h>
struct __attribute__((__packed__)) BitmapHeader
{
int width;
int height;
};
void loadBmp(char* filePath, struct BitmapHeader bmpHeaderInfo){
FILE* filePtr = fopen(filePath, "rb");
unsigned char header[54];
fread(header, sizeof(unsigned char), 54, filePtr);
}
int main(){
char path2BMP[] = "/cup.bmp";
struct BitmapHeader bmpHeaderInfo = {0};
loadBmp(path2BMP, bmpHeaderInfo);
return 0;
}
I have a kernel module where I would like to pass some values into User Space. Someone suggested me to use struct type to pass more values.
In kernel space I have:
typedef struct data {
int val_delta;
int val_btn_status;
}data_t;
static ssize_t sample_read(struct file *filp, char *buffer, size_t length, loff_t * offset)
{
int ret = 1;
int delta = 10;
data_t val;
val.val_btn_status = gpio_get_value( BTN );
val.val_delta = delta;
copy_to_user( buffer, &val, sizeof(data_t));
return( ret );
}
In User space how can I take the two values into data_t struct?
I thought to declare also in User Space the data_t type as:
typedef struct data {
int val_delta;
int val_btn_status;
}data_t;
int main(int argc, char **argv)
{
data_t str;
char *app_name = argv[0];
char *dev_name = "/dev/sample";
int fd = -1;
if ((fd = open(dev_name, O_RDWR)) < 0)
{
fprintf(stderr, "%s: unable to open %s: %s\n", app_name, dev_name, strerror(errno));
return( 1 );
}
x = read(fd, &str, 1);
return 0;
}
but I don't like this because I wouldn't like to rewrite both on User Space and on Kernel Space the same typedef, and maybe this one doesn't work. There are other solutions?
You can add the common struct and the dev_name in to a header and include in the driver and the user space program.
Like: data.h
#ifndef DATA_H
#define DATA_H
typedef struct data {
int val_delta;
int val_btn_status;
}data_t;
#define dev_name "/dev/sample"
#endif
Also change
read(fd, &str, 1);
to
read(fd, &str, sizeof(data_t));
Firstly, you need to understand the copy_to_user() def.
unsigned long copy_to_user ( void __user * to,
const void * from,
unsigned long n);
In your sample sample_read() function should use char __user *buffer instead of char *buffer.
Put your typedef struct data definition into a header file which can be included both kernel module and user program instead of redefining it twice.
Refer to thread
Have you tried other options, like marking your ECHO interrupt from the sensor (I'm assuming that it'll be an interrupt) as a fast interrupt so it won't be pre-empted by others at the same level.
Or why not have it at the highest available interrupt level on your processor (beneath the hard coded ones).
As Santosh says there has to be a different reason for the freeze. Perhaps have you looked at the alignment of your given structure? In accordance to your underlying processor's word length??
This is got me pretty stuck, how do I fix this? I know I haven't got error checking, but they aren't required i'd guess since it's restricted to my desktop. It obveously can't be EOF. It's for the infoheader struct, fileheader works fine. Do i need to take a new line or something?
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
unsigned char fileMarker1; /* 'B' */
unsigned char fileMarker2; /* 'M' */
unsigned int bfSize;
unsigned short unused1;
unsigned short unused2;
unsigned int imageDataOffset; /* Offset to the start of image data */
}FILEHEADER;
typedef struct
{
unsigned int biSize;
int width; /* Width of the image */
int height; /* Height of the image */
unsigned short planes;
unsigned short bitPix;
unsigned int biCompression;
unsigned int biSizeImage;
int biXPelsPerMeter;
int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
}INFOHEADER;
typedef struct
{
unsigned char b; /* Blue value */
unsigned char g; /* Green value */
unsigned char r; /* Red value */
}IMAGECOMPONENT;
int fileheadfunc(FILE *image);
int infoheadfunc(FILE *image);
int main( int argc, char *argv[] )
{
char *filename; /* *threshholdInput = argv[2]; */
FILE *image;
int filehead, infohead;
filename = argv[1];
/* int threshhold = atoi(threshholdInput); */
if (argc != 2)
{
printf(" Incorrect Number Of Command Line Arguments\n");
return(0);
}
image = fopen( filename, "r");
if (image == NULL)
{
fprintf(stderr, "Error, cannot find file %s\n", filename);
exit(1);
}
filehead = fileheadfunc(image);
infohead = infoheadfunc(image);
fclose(image);
return(0);
}
int fileheadfunc(FILE *image)
{
FILEHEADER *header;
long pos;
fseek (image , 0 , SEEK_SET);
fread( (unsigned char*)header, sizeof(FILEHEADER), 1, image );
if ( (*header).fileMarker1 != 'B' || (*header).fileMarker2 != 'M' )
{
fprintf(stderr, "Incorrect file format");
exit(1);
}
printf("This is a bitmap!\n");
pos = ftell(image);
printf("%ld\n", pos);
printf("%zu\n", sizeof(FILEHEADER));
return(0);
}
int infoheadfunc(FILE *image)
{
INFOHEADER *iheader;
fseek (image, 0, SEEK_CUR );
fread( (unsigned int*)iheader, sizeof(INFOHEADER), 1, image );
printf("Width: %i\n", (*iheader).width);
printf("Height: %i\n", (*iheader).height);
return(0);
}
You're not actually allocating any storage for the BMP header data structures, e.g. you need to change this:
int fileheadfunc(FILE *image)
{
FILEHEADER *header;
long pos;
fseek(image, 0, SEEK_SET);
fread((unsigned char*)header, sizeof(FILEHEADER), 1, image);
...
to this:
int fileheadfunc(FILE *image)
{
FILEHEADER header; // <<<
long pos;
fseek(image, 0, SEEK_SET);
fread(&header, sizeof(FILEHEADER), 1, image); // <<<
...
Also, as previously noted in one of the comments above, you need #pragma pack(1) (or equivalent if you're not using gcc or a gcc-compatible compiler) prior to your struct definitions to eliminate unwanted padding. (NB: use #pragma pack() after your struct definitions to restore normal struct padding/alignment.)
There are two problems with the code:
Alignment
For performance reasons the compiler will, unless instructed to do otherwise, arrange struct fields on its "natural boundaries", effectively leaving uninitialised gaps between byte-size fields. Add
#pragma pack(1)
before the struct definitions and you should be fine. It's also easy to test: just print out the struct size without and with pragma pack in place, and you'll see the difference.
Allocation
As Paul R already said, you should allocate space for the headers, not just provide a pointer to the structures. The fact that fileheadfunc works is a coincidence, there just wasn't anything in the way that got smashed when data got written outside of the allocated space.
A last one, just for prevention sake: should you ever want to return the read structures to the calling program, do not just return a pointer to the structure allocated in the function as that will cause problems similat to the unallocated variables you have now. Allocate them in the calling function, and pass a pointer to that variable to the header read functions.
EDIT clarification regarding the last point:
DON'T
FILEHEADER * fileheadfunc(FILE *image)
{
FILEHEADER header;
...
return &header; // returns an address on the function stack that will
// disappear once you return
}
DO
int fileheadfunc(FILE *image, FILEHEADER *header)
{
...
}
which will be called like this
...
FILEHEADER header;
returnvalue = fileheaderfunc(imagefile,&header);
EDIT2: just noticed that the way you read the DIB header is not correct. There are several variations of that header, with different sizes. So after reading the file header you first need to read 4 bytes into an unsigned int and based on the value read select the correct DIB header structure to use (don't forget you already read its first field!) or tell the user you encountered an unsupported file format.