I'm trying to write a program that reads a text file into a 2D array of structs, but trying to put a struct into that array causes the program to crash.
Here's the program
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 && width <= 1024 && height > 0 && 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
}
relevant info from 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
If anyone can help me figure out what's causing my program to crash there, I would appreciate it.
Thank you!
A few problems:
1: img.pixels is never initialized. Anytime you create a pointer to something without assigning it a value first, try to set it to NULL so it's easier to debug. Note that this will not fix the issue. To fix it, simply initialize them with a struct instance.
2: You should free pixelarr. Most modern OS's do this, but it's still really, really good practice.
3: Wouldn't it be easier to not use the nested loops, and instead do img.pixels = pixelarr? It achieves the same (unless this is for a class, and this part is required).
Related
// A part of Code
int dim1=height;
int dim2=width;
int dim3=3;
int k;
unsigned char *** image = (unsigned char ***)malloc(dim1*dim2*3);
for (i = 0; i< dim1; i++) {
image[i] = (unsigned char **)malloc(dim2*sizeof(unsigned char *));
for (j = 0; j < dim2; j++) {
image[i][j] = (unsigned char *)malloc(dim3*sizeof(unsigned char ));
}
}
// B part of Code
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
fread(&image[i][j][0],sizeof(unsigned char),1,fp);
fread(&image[i][j][1],sizeof(unsigned char),1,fp);
fread(&image[i][j][2],sizeof(unsigned char),1,fp);
}
}
As you can see from above I am trying to declare a 3d array that will contain the pixel information of a bmp image. The fp pointer is to a binary file that the data is contained there.
My question is how is it possible when I try to fread using dynamic memory allocation to get wrong results in image table (meaning a blank image is printed even though the rest of my code that i dont include here is correct).
On the other hand when i remove the A part of the Code and replace it with "unsigned char image[height][width][3]" it works.
So what am i doing wrong in the memory allocation or in the use of fread? Because obviously the problem is there.
In order to make it easier lets assume that the size is 252x252x3.
typedef struct
{
unsigned char R;
unsigned char G;
unsigned char B;
}RGB;
void *allocateReadImage(size_t width, size_t height, FILE *fi)
{
RGB (*picture)[width] = malloc(sizeof(*picture) * height);
if(picture && fi)
{
if(fread(picture, sizeof(*picture), height, fi) != height)
{
free(picture);
picture = NULL;
}
}
return picture;
}
usage:
RGB *mypicture = allocateReadImage(1600, 1200, inputfile);
if(!mypicture) { /*some error handling*/ }
My function is getting an Image and I am trying to crop the BMP image
by size: 100 x 100, 200 x 200, 300 x 300, 400 x 400 by Pixels ,
i don't know what to do make it work. please help me
The size of the image is int height and int width and the function knows the values in pixels.
Here is my code:
void re_allocate_pixels(struct RGB_Image *image, int new_height, int new_width)
{
int org_height = image->height;
int org_width = image->width;
int org_size = image->size;
int i;
struct Pixel **pxls;
pxls = (struct Pixel **)malloc((org_height) * sizeof(struct Pixel *));
if (pxls == NULL)
{
printf("Memory allocation failed\n");
exit(1);
}
for (i = 0; i < org_height; i++)
{
pxls[i] = (struct Pixel *)malloc(org_width * sizeof(struct Pixel));
if (pxls[i] == NULL)
{
printf("Memory allocation failed\n");
exit(1);
}
}
//i have no idea what to do next to crop the image and pixecl
/*for (int j = 0; j < org_height; j++)
{
for (int k = 0; k < org_width; k++)
{
pxls[i][j] = pxls[k][j];
}
}*/
}
here are struct data:
struct Pixel
{
unsigned char red;
unsigned char green;
unsigned char blue;
};
struct RGB_Image
{
char file_name[MAX_FILE_NAME_SIZE];
long height;
long width;
long size;
struct Pixel **pixels;
};
here is how am calling this function
struct RGB_Image *rgb_img_ptr;
struct RGB_Image image;
rgb_img_ptr = ℑ
int image_load_ret_value = load_image(rgb_img_ptr);
re_allocate_pixels(rgb_img_ptr, 100,100); // here is calling
You have to delete the old allocation and also assign the new size value. size usually refers to "width in bytes" multiplied by height.
In this case the value for "width in bytes" should be "width * 3", and it should always be a multiple of 4.
Read the image one row at a time. Use mempcy to copy each row.
Note that bitmaps are usually upside down. You may have to change the loop to for (int y = dst.height - 1; y >=0; y--){memcpy...}
void re_allocate_pixels(struct RGB_Image *image, int new_height, int new_width)
{
if(new_width > image->width) return;
if(new_height > image->height) return;
struct RGB_Image *src = image;
struct RGB_Image dst;
dst.width = new_width;
dst.height = new_height;
//allocate memory
dst.pixels = malloc(dst.height * sizeof(struct Pixel*));
for(int y = 0; y < dst.height; y++)
dst.pixels[y] = malloc(dst.width * sizeof(struct Pixel));
//copy from source to destination
for(int y = 0; y < dst.height; y++)
memcpy(dst.pixels[y], src->pixels[y], dst.width * sizeof(struct Pixel));
//free the old allocation
for(int y = 0; y < src->height; y++)
free(image->pixels[y]);
free(image->pixels);
//assing new allocation
image->pixels = dst.pixels;
//set the new width, height, size
image->width = dst.width;
image->height = dst.height;
int bitcount = 24;
int bytecount = 3; //<- same as sizeof(struct Pixel)
//calculate width in bytes
int width_in_bytes = ((dst.width * bitcount + 31) / 32) * 4;
image->size = width_in_bytes * dst.height;
}
I'm new to C Programming and want to focus on learning dynamic allocation. As a learning opportunity for me, I'm trying to create a function that returns a double-pointer for a 2D array of structs. I've been referencing tutorials that generally refer to what is mentioned here in approach #3.
I can see that the tutorial assigns integer values no problem, but I'm not sure how that translates with structs.
Here's my code so far:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
const int HEIGHT = 64;
const int WIDTH = 96;
struct Tile
{
char type;
bool armed;
struct Tile* up;
struct Tile* right;
struct Tile* down;
struct Tile* left;
};
struct Tile** createTileMap(unsigned int w, unsigned int h)
{
struct Tile** map = (struct Tile **)malloc(w * sizeof(struct Tile *));
for (int x = 0; x < w; x++)
{
map[x] = (struct Tile *)malloc(h * sizeof(struct Tile));
for (int y = 0; y < h; y++)
{
map[x][y] = (struct Tile){.type = '_', .armed = false, .up = NULL,
.right = NULL, .down = NULL, .left = NULL};
}
}
}
int main(int argc, char* argv[])
{
struct Tile** map = createTileMap(WIDTH, HEIGHT);
for (int x = 0; x < WIDTH; x++)
{
for (int y = 0; y < HEIGHT; y++)
{
printf(" (%d, %d): ", x, y);
printf("%c", map[x][y].type);
}
printf("\n");
}
return 0;
}
This code segfaults, and I'm not too sure why. Any help is appreciated.
As indicated by EOF, I simply forgot to actually return the address. Fortunately my other code was fine, though!
Why would I be getting a seg fault at the highlighted line. Am I accessing the 2d array wrong? tempMap is a 1d array with all the values for the 2d array, for example [0,1,0,0,0,0,1,0] and since I know the number of rows and columns I am trying to make it into a 2d array of Spaces (which is my struct). Any help is very much appreciated.
int opt;
char *filename = NULL;
Space **map;
char *tempMap;
if (i != 0){
int col = getCol(filename);
int row = getRow(filename, col);
printf("%d x %d\n", row, col);
map = create_map(row, col, filename);
tempMap = populate_map(map, filename);
int curIndx=0;
for (int l = 0; l < 100; ++l) {
printf("%c", tempMap[l]);
}
for (int j = 0; j < row; ++j) {
for (int k = 0; k < col; ++k) {
map[j][k] = makeNewSpace(tempMap[curIndx],row,col); //<-----------This Line
curIndx++;
}
}
}
Also here is the makeNewSpace()
Space makeNewSpace(char character, int row, int column){
Space space;
space.character = character;
space.isVisited = false;
space.row= row;
space.column = column;
return space;
}
And this is where I allocate space for the 2d array.
Space **create_map( int row, int col, char *fileName) {
Space *values = calloc(row * col, 2* sizeof(char) + (4 * sizeof(int)));
Space **map = malloc(row * sizeof(char *));
for (int i = 0; i < row; ++i) {
map[i] = values + i * col;
}
return map;
}
Lastly here is my struct
typedef struct Space{
char character;
bool isVisited;
int row;
int column;
}Space;
Not sure if this is what you're going for, a dynamically allocated 2d array of Space structs.
#include <stdio.h>
#include <stdlib.h>
// Space struct definition
typedef struct {
int data;
} Space;
int main() {
int i;
// Allocate memory for the rows
Space** space2d = malloc(sizeof(Space*) * 3);
// Allocate memory for the columns
for(i = 0; i < 3; ++i) {
space2d[i] = malloc(sizeof(Space) * 5);
}
// Example setting one of the struct's members inside the 2d array
space2d[0][0].data = 100;
printf("%d\n", space2d[0][0].data);
// Freeing the 2d array
for(i = 0; i < 3; ++i)
free(space2d[i]);
free(space2d);
}
#include <stdio.h>
#include <stdlib.h>
#define MAX_ROWS 5
#define MAX_COLS 5
int globalvariable = 100;
void CreateMatrix(int ***Matrix)
{
int **ptr;
char *cp;
int i = 0;
*Matrix = (int**)malloc((sizeof(int*) * MAX_ROWS) + ((MAX_ROWS * MAX_COLS)*sizeof(int)));
ptr = *Matrix;
cp = (char*)((char*)*Matrix + (sizeof(int*) * MAX_ROWS));
for(i =0; i < MAX_ROWS; i++)
{
cp = (char*)(cp + ((sizeof(int) * MAX_COLS) * i));
*ptr = (int*)cp;
ptr++;
}
}
void FillMatrix(int **Matrix)
{
int i = 0, j = 0;
for(i = 0; i < MAX_ROWS; i++)
{
for(j = 0; j < MAX_COLS; j++)
{
globalvariable++;
Matrix[i][j] = globalvariable;
}
}
}
void DisplayMatrix(int **Matrix)
{
int i = 0, j = 0;
for(i = 0; i < MAX_ROWS; i++)
{
printf("\n");
for(j = 0; j < MAX_COLS; j++)
{
printf("%d\t", Matrix[i][j]);
}
}
}
void FreeMatrix(int **Matrix)
{
free(Matrix);
}
int main()
{
int **Matrix1, **Matrix2;
CreateMatrix(&Matrix1);
FillMatrix(Matrix1);
DisplayMatrix(Matrix1);
FreeMatrix(Matrix1);
getchar();
return 0;
}
If the code is executed, I get the following error messages in a dialogbox.
Windows has triggered a breakpoint in sam.exe.
This may be due to a corruption of the heap, which indicates a bug in sam.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while sam.exe has focus.
The output window may have more diagnostic information.
I tried to debug in Visual Studio, when printf("\n"); statement of DisplayMatrix() is executed, same error message is reproduced.
If I press continue, it prints 101 to 125 as expected. In Release Mode, there is no issue !!!.
please share your ideas.
In C it is often simpler and more efficient to allocate a numerical matrix with calloc and use explicit index calculation ... so
int width = somewidth /* put some useful width computation */;
int height = someheight /* put some useful height computation */
int *mat = calloc(width*height, sizeof(int));
if (!mat) { perror ("calloc"); exit (EXIT_FAILURE); };
Then initialize and fill the matrix by computing the offset appropriately, e.g. something like
for (int i=0; i<width; i++)
for (int j=0; j<height; j++)
mat[i*height+j] = i+j;
if the matrix has (as you show) dimensions known at compile time, you could either stack allocate it with
{ int matrix [NUM_COLS][NUM_ROWS];
/* do something with matrix */
}
or heap allocate it. I find more readable to make it a struct like
struct matrix_st { int matfield [NUM_COLS][NUM_ROWS]; };
struct matrix_st *p = malloc(sizeof(struct matrix_st));
if (!p) { perror("malloc"); exit(EXIT_FAILURE); };
then fill it appropriately:
for (int i=0; i<NUM_COLS; i++)
for (int j=0; j<NUM_ROWS, j++)
p->matfield[i][j] = i+j;
Remember that malloc returns an uninitialized memory zone so you need to initialize all of it.
A two-dimensional array is not the same as a pointer-to-pointer. Maybe you meant
int (*mat)[MAX_COLS] = malloc(MAX_ROWS * sizeof(*mat));
instead?
Read this tutorial.
A very good & complete tutorial for pointers, you can go directly to Chapter 9, if you have in depth basic knowledge.