grininmonkey
Posts: 92
Joined: Mon Jul 30, 2018 3:44 pm

I am missing some fundamental understanding of C?

Tue Oct 16, 2018 2:56 pm

I am working on some "learning" exercises where I want to define image functions in one file and call them from another etc... so I am now expanding beyone one huge main()...

Anyway, I figured out the cflags and gcc options etc to go beyond a single c file... and initially I had my render image to frame buffer test working until I worked on moving the action of rendering if you call it that... to my image.c file.

I am a bit stumped here, because I get a segment fault (core dumped) error when I call a function which executes the framebuffer pixel function from a dedicated function for that task.... but do not get segment fault if its called within another function within the same file, or do I get a segment fault error if I iterate and call the framebuffer pixel function with my main.c ...

I don't believe I am explaining this well... so I added comments within the code spinets below. I added some printf calls within the iteration of the image.c "render" function to see where it fails as an experiment.... what I can't understand... is all of a sudden there is an out of bounds during the iteration.... as if the proceeding free function in main.c is acting against the struct var before the image.c render is completed... which shouldn't be the case right?

Per my subject line... I believe I am missing some fundamentals here ?


main.c

Code: Select all


. . . . . . . . .

#include "../../include/image.h"

int
main(int argc, char**  argv)
{
	/* int result; */

	lfb_init();

	Image test;
	test.xoffset = 400;
	test.yoffset = 40;
	image_load_png(&test,"/home/gmonkey/Projects/C/fallout-fb-console/src/fbui/assets/terminal_test.png");
     /* generates segment fault error */  	
    /* image_render(&test); */  


    /*  This works fine -- no issue */	
	for (int y=0; y < test.height; y++)
		for (int x=0; x < test.width; x++)
			lfb.putpixel(x+test.xoffset,y+test.yoffset,test.data[x][y]);

	image_free(&test);

	return EXIT_SUCCESS;
}


image.c file

Code: Select all


. . . . . . . .

	for (y=0; y<image->height; y++) {
		png_byte* row = row_pointers[y];
		for (x=0; x<image->width; x++) {
			png_byte* ptr = &(row[x * bytes_pp]);
			image->data[x][y] = ptr[0] << 16 | ptr[1] << 8 | ptr[2];
			/* lfb.putpixel(x,y,lfb.bg_image[x][y]); */    // <--- This works fine
		}
	}

}

void image_render(Image *image)
{
	/* generates Segment Fault error .... why?? */
	for (int y=0; y < image->height; y++)
		for (int x=0; x < image->width; x++)
			lfb.putpixel(x+image->xoffset,y+image->yoffset,image->data[x][y]);
			/* lfb.putpixel(x,y,image->data[x][y]); */ 
}

void image_free(Image *image)
{
	for(int i=0;i<image->height;i++)
		free(image->data[i]);
	free(image->data);
}


jamesh
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 20697
Joined: Sat Jul 30, 2011 7:41 pm

Re: I am missing some fundamental understanding of C?

Tue Oct 16, 2018 3:27 pm

Where are the variables used in the image function declared? I wonder if you have two sets defined, and its using uninitialised ones. You'll probably need to provide the entire functions to be clearer.
Principal Software Engineer at Raspberry Pi (Trading) Ltd.
Please direct all questions to the forum, I do not do support via PM.

ericcooper
Posts: 110
Joined: Sat Apr 08, 2017 6:23 pm

Re: I am missing some fundamental understanding of C?

Tue Oct 16, 2018 3:28 pm

I can't tell what's wrong without seeing more of the code (definition of the Image struct, declaration of the lfb variable), but I'd suggest running your program under the debugger, gdb. (You'll have to compile your code with the -g flag.) Then you can inspect the values of variables when the fault occurs, etc.

User avatar
buja
Posts: 474
Joined: Wed Dec 31, 2014 8:21 am
Location: Netherlands

Re: I am missing some fundamental understanding of C?

Tue Oct 16, 2018 3:38 pm

What does this mean?

Code: Select all

lfb.putpixel(x+test.xoffset,y+test.yoffset,test.data[x][y]);
putpixel looks like a function to me, with 3 arguments, but what does lfd.putpixel() mean? (I don't understand the dot notation here)
Last edited by buja on Tue Oct 16, 2018 3:41 pm, edited 1 time in total.

danjperron
Posts: 3072
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: I am missing some fundamental understanding of C?

Tue Oct 16, 2018 3:41 pm

lfb.putpixel this looks like c++ not C.

Please provide the name of the library you are using and the headers info of your source files. The include stuff at the beginning.

I think that you need to pass lfb into your function but since we don't know which libraries or missing function you are using it is hard to figure it out.

grininmonkey
Posts: 92
Joined: Mon Jul 30, 2018 3:44 pm

Re: I am missing some fundamental understanding of C?

Tue Oct 16, 2018 4:25 pm

There are few files in the chain.... I am essentially assembling various examples and trying to figure out how to construct as one project (per say)...

Code: Select all

include/
    libfb.h
    image.h
src/
    libfb.c
    libfb.o
    libfb.so
    fbui/
        image.c
        main.c

Headers....

Code: Select all

/**
	@file libfb.h
*/
#include <stddef.h>

#define YELLOW	0xFFFF00
#define GRAY	0x888888
#define GREEN	0x00FF00
#define BLUE	0x0000FF
#define RED		0xFF0000
#define WHITE	0xFFFFFF
#define BLACK	0x000000

#if 0
/* colors 8bpp */
#define BLACK			0
#define BLUE			1
#define GREEN			2
#define CYAN			3
#define RED				4
#define MAGENTA			5
#define BROWN			6
#define WHITE			7
#define GRAY			8
#define	LIGHT_BLUE		9
#define	LIGHT_GREEN		10
#define LIGHT_CYAN		11
#define LIGHT_RED		12
#define	LIGHT_MAGENTA	13
#define YELLOW			14
#define LIGHT_WHITE		15
#endif

typedef unsigned char byte;

/**
	Initialize values and function pointers in lfb.
*/

void abort_(const char * s, ...);
void lfb_init();

typedef struct{
	int x;
	int y;
} Point;

typedef int Color;

/**
	lfb
*/
#ifdef DOXYGEN
typedef struct {
#else
struct {
#endif
	char id[18]; /*!< Framebuffer driver identification string */
	int bytes_per_line;
	int width;
	int height;
	int bpp;
	void (*memset)(void *dst, unsigned int data, size_t n);
	void (*fillscr)(Color c);
	void (*fillbox)(int, int, int, int, Color);
	void (*drawline)(Point a, Point b, int width, Color c);
	void (*drawpolygon)(Point *, int, Color);
	void (*drawtriangle)(Point[3], int, Color);
	void (*setpixel)(int offset, Color);
	void (*putpixel)(int, int, Color);
	void (*refresh)();
	uint32_t (*convert_color)(unsigned int,unsigned int);
} lfb;

Code: Select all

/**
	@file image.h
*/

typedef struct {
	int width;
	int height;
	int xoffset;
	int yoffset;
	int allocated;
	uint32_t **data;
} Image;

void image_load_png(Image *image, char* file_name);
/* void image_load_text(); */ // add freefont2 functions
void image_render(Image *image);
void image_free(Image *image);

C files

libfb.c

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <math.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <stdarg.h>
#include <png.h>

#include "../include/libfb.h"

#define DELTA(x,y) ((x) - (y))

int fb;
byte *scr;

void lfb_memset8(void *, unsigned int, size_t);
void lfb_memset16(void *, unsigned int, size_t);
void lfb_memset32(void *, unsigned int, size_t);

void lfb_fill_scr(Color);
void lfb_fill_box(int x, int y, int w, int h, Color);

void lfb_draw_line(Point, Point, int, Color);
void lfb_draw_polygon(Point *, int, Color);
void lfb_draw_triangle(Point[3], int, Color);

void lfb_set_pixel8(int, Color);
void lfb_set_pixel16(int, Color);
void lfb_set_pixel32(int, Color);
void lfb_put_pixel(int, int, Color);

void lfb_refresh();

void lfb_exit_error(char *);
uint32_t lfb_convert_color(unsigned int,unsigned int);

struct fb_var_screeninfo fb_var_info;
struct fb_fix_screeninfo fb_fix_info;

void abort_(const char * s, ...)
{
	va_list args;
	va_start(args, s);
	vfprintf(stderr, s, args);
	fprintf(stderr, "\n");
	va_end(args);
	abort();
}

void lfb_init()
{
	char *FB_DEV = getenv("FRAMEBUFFER");
	if(FB_DEV == NULL){
		FB_DEV = "/dev/fb0";
	}
	fb = open(FB_DEV, O_RDWR);
	if(fb < 0){
		fb = open("/dev/graphics/fb0", O_RDWR);
		if(fb < 0)
			lfb_exit_error("Can`t open /dev/graphics/fb0\n");
	}

	if(ioctl(fb, FBIOGET_VSCREENINFO, &fb_var_info) == -1) {
		perror("Error reading variable information");
		exit(2);
	}
	if(ioctl(fb, FBIOGET_FSCREENINFO, &fb_fix_info) == -1) {
		perror("Error reading fixed information");
		exit(3);
	}

	// set some constants
	strncpy(lfb.id, fb_fix_info.id, sizeof(lfb.id));
	lfb.bytes_per_line = fb_fix_info.line_length;
	lfb.width = fb_var_info.xres;
	lfb.height = fb_var_info.yres;
	lfb.bpp = fb_var_info.bits_per_pixel;

	lfb.fillbox = &lfb_fill_box;
	lfb.drawpolygon = &lfb_draw_polygon;
	lfb.drawtriangle = &lfb_draw_triangle;
	lfb.fillscr = &lfb_fill_scr;
	lfb.drawline = &lfb_draw_line;
	lfb.refresh = &lfb_refresh;
	lfb.putpixel = &lfb_put_pixel;
	lfb.convert_color = &lfb_convert_color;

	switch(lfb.bpp){
		case 8:
			lfb.memset = &lfb_memset8;
			lfb.setpixel = &lfb_set_pixel8;
			break;
		case 16:
			lfb.memset = &lfb_memset16;
			lfb.setpixel = &lfb_set_pixel16;
			break;
		case 24:
		case 32:
			lfb.memset = &lfb_memset32;
			lfb.setpixel = &lfb_set_pixel32;
			break;
	}

	//printf("Screen size %dx%d\n", lfb.width, lfb.height);

	scr = (unsigned char *) mmap(0, fb_fix_info.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0);
	scr+= (fb_var_info.xoffset + fb_var_info.yoffset * fb_var_info.xres_virtual) * (fb_var_info.bits_per_pixel >> 3);

}

void lfb_cleanup()
{

}

void lfb_fill_scr(Color c)
{
	lfb.memset(scr, c, lfb.width * lfb.height );
}

void lfb_fill_box(int x, int y, int w, int h, Color color)
{
	int cy;

	if(x+w > lfb.width) w = lfb.width - x;
	if(y+h > lfb.height) h = lfb.height - y;

	for(cy = y; cy < y + h; cy++)
		lfb.memset((unsigned int *)(scr + ((lfb.bytes_per_line) * cy + x)), color, w);
}

/* Modifyed copy from https://github.com/ssloy/tinyrenderer/wiki/Lesson-1:-Bresenham%E2%80%99s-Line-Drawing-Algorithm
	...lets be honest, I couldn't even implement it correctly :/
*/
void lfb_draw_line(Point pa, Point pb, int width, Color color)
{
	bool steep = false;
	int x;
	Point *start = &pa, *end = &pb, *tmp;

	if(abs(pa.x - pb.x) < abs(pa.y - pb.y)){
		start = &(Point){.x = pa.y, .y = pa.x};
		end = &(Point){.x = pb.y, .y = pb.x};
		steep = true;
	}
	if(start->x > end->x){
		tmp = start;
		start = end;
		end = tmp;
	}

	int dx = end->x - start->x;
	int dy = end->y - start->y;
	int derror2 = abs(dy)*2;
	int error2 = 0;

	for(x = start->x; x <= end->x; x++){
		float t = (x-start->x)/(float) (end->x - start->x);
		int y = start->y * (1.-t) + end->y*t;
		if (steep){
			lfb.putpixel(y, x, color);
		} else {
			lfb.putpixel(x, y, color);
		}
		error2 += derror2;
		if(error2 > dx) {
			y += (end->y > start->y?1:-1);
			error2 -= dx * 2;
		}
	}

}

void lfb_draw_polygon(Point *points, int w, Color c)
{
	Point *p = points;

	while(p->x > 0 && p->y > 0 && (p+1)->x > 0 && (p+1)->y > 0){
		lfb.drawline(*p, *(p+1),  w, c);
		p++;
	}
	lfb.drawline(*p, *points,  w, c); // close polygon
}

void lfb_draw_triangle(Point p[3], int w, Color c)
{
	int i;
	for(i = 0; i < 2; i++){
		lfb.drawline(p[i], p[i+1],  w, c);
	}
	lfb.drawline(p[2], p[0],  w, c); // close triangle
}

void lfb_set_box(int x, int y, int w, int h)
{
	int i;

	if(x + w > lfb.width && y + h > lfb.height){
		for(i = y; i < h; i++);
		//	lfb_set_line(
	}
}

int lfb_comp_point(Point *pa, Point *pb)
{
	if(pa->x == pb->x && pa->y == pb->y) {
		return EXIT_SUCCESS;
	} else {
		return -1;
	}
}

void lfb_add_point(Point *pa, Point *pb, Point *pr)
{
	pr->x = pa->x + pb->x;
	pr->y = pa->y + pb->y;
}

void lfb_exit_error(char *str)
{
	write(1, str, strlen(str));
	exit(1);
}

void lfb_memset8(void *dst, unsigned int b, size_t len){
	memset(dst, b, len);
}

void lfb_memset16(void *dst, unsigned int b, size_t len){
	int i;
	uint16_t *dst_16;
	for(i=0; i < len * 2; i++){
		dst_16 = (uint16_t *) dst + i;
		*dst_16 = (uint16_t)b;
	}
}

void lfb_memset32(void *dst, unsigned int b, size_t len){
	wmemset(dst, b, len);
}

void lfb_set_pixel8(int offset, Color c){
	if(offset < 0) offset = 0;
	if(offset > lfb.width * lfb.height) offset = lfb.width * lfb.height;
	*(scr + offset) = (char) c;
}

void lfb_put_pixel(int x, int y, Color c){
	lfb.setpixel(x + (lfb.width * y), c);
}

void lfb_set_pixel16(int offset, Color c){
	if(offset < 0) return;
	if(offset > lfb.width * lfb.height) return;
	*(uint16_t *) (scr + (offset *2)) = c;
}

void lfb_set_pixel32(int offset, Color c){
	if(offset < 0) return;
	if(offset > lfb.width * lfb.height) return;
	*(unsigned int *) (scr + (offset *4)) = c;
}

void lfb_refresh()
{
	fb_var_info.activate |= FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
	fb_var_info.yres_virtual = fb_var_info.yres * 2;
	fb_var_info.yoffset = fb_var_info.yres;
	ioctl(fb, FBIOGET_VSCREENINFO, &fb_var_info);
}

/*
	Added to set color from freetype2 blue to specified color
*/
uint32_t lfb_convert_color(unsigned int color, unsigned int bc)
{
    bc += 1;

    unsigned int r = color & 0x00ff0000;
    unsigned int g = color & 0x0000ff00;
    unsigned int b = color & 0x000000ff;

    r = (r * bc) & 0xff000000;
    g = (g * bc) & 0x00ff0000;
    b = (b * bc) & 0x0000ff00;

    unsigned int dst = (color & 0x00000000) | ((r | g | b) >> 8);

	return dst;
}
image.c

Code: Select all

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include <png.h>
#include <libfb.h>
#include "../../include/image.h"

png_byte bit_depth;
int number_of_passes;

void image_load_png(Image *image, char* file_name)
{
	int x, y;
	png_byte color_type;
	png_structp png_ptr;
	png_infop info_ptr;
	png_bytep * row_pointers;

	uint8_t  header[8];	/* 8 is the maximum size that can be checked */

	FILE *fp = fopen(file_name, "rb");

	if (!fp)
		abort_("[read_png_file] File %s could not be opened for reading", file_name);

	if ( 8!=fread(header, 1, 8, fp) )
        abort_("[read_png_file] File %s could not read PNG signature bytes", file_name);

	if (png_sig_cmp(header, 0, 8))
		abort_("[read_png_file] File %s is not recognized as a PNG file", file_name);

	/* initialize stuff */
	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

	if (!png_ptr)
		abort_("[read_png_file] png_create_read_struct failed");

	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
		abort_("[read_png_file] png_create_info_struct failed");

	if (setjmp(png_jmpbuf(png_ptr)))
		abort_("[read_png_file] Error during init_io");

	png_init_io(png_ptr, fp);
	png_set_sig_bytes(png_ptr, 8);
	png_read_info(png_ptr, info_ptr);

	image->width = png_get_image_width(png_ptr, info_ptr);
	image->height = png_get_image_height(png_ptr, info_ptr);
	color_type = png_get_color_type(png_ptr, info_ptr);
	bit_depth = png_get_bit_depth(png_ptr, info_ptr);

	/* allocate memory for image.data  */
	if (image->allocated > 1)
		image_free(image);

	image->data = (uint32_t **) calloc(image->width,sizeof(uint32_t*));
	for (int i = 0; i < image->width; i++)
		image->data[i] = (uint32_t *) calloc(image->height,sizeof(uint32_t));
	image->allocated = 2;

	if(color_type == PNG_COLOR_TYPE_PALETTE)
		png_set_expand(png_ptr);

	number_of_passes = png_set_interlace_handling(png_ptr);
	png_read_update_info(png_ptr, info_ptr);

	/* read file */
	if (setjmp(png_jmpbuf(png_ptr)))
		abort_("[read_png_file] Error during read_image");

	row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * image->height);
	for (y=0; y<image->height; y++)
		row_pointers[y] = (png_byte*) malloc(png_get_rowbytes(png_ptr,info_ptr));

	png_read_image(png_ptr, row_pointers);

	fclose(fp);

	/* process file */
	int bytes_pp = 4;

	if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_RGB)
		bytes_pp = 3;
	else
		if (png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_RGBA)
			abort_("[process_file] color_type of input file must be PNG_COLOR_TYPE_RGBA (%d) (is %d)",
				PNG_COLOR_TYPE_RGBA, png_get_color_type(png_ptr, info_ptr));

	for (y=0; y<image->height; y++) {
		png_byte* row = row_pointers[y];
		for (x=0; x<image->width; x++) {
			png_byte* ptr = &(row[x * bytes_pp]);
			image->data[x][y] = ptr[0] << 16 | ptr[1] << 8 | ptr[2];
			/* lfb.putpixel(x,y,lfb.bg_image[x][y]); */
		}
	}

}

void image_render(Image *image)
{
	for (int y=0; y < image->height; y++)
		for (int x=0; x < image->width; x++)
			lfb.putpixel(x+image->xoffset,y+image->yoffset,image->data[x][y]);
}

void image_free(Image *image)
{
	for(int i=0;i<image->height;i++)
		free(image->data[i]);
	free(image->data);
}

main.c

Code: Select all

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdarg.h>

#include <libfb.h>
#include "../../include/image.h"

int
main(int argc, char**  argv)
{
	/* int result; */

	lfb_init();

	Image test;
	test.xoffset = 400;
	test.yoffset = 40;
	image_load_png(&test,"/home/gmonkey/Projects/C/fallout-fb-console/src/fbui/assets/terminal_test.png");
	
    /* image_render(&test); */ // <--- Segment Fault ??

	// Works just fine
	for (int y=0; y < test.height; y++)
		for (int x=0; x < test.width; x++)
			lfb.putpixel(x+test.xoffset,y+test.yoffset,test.data[x][y]);

	image_free(&test);

	return EXIT_SUCCESS;
}

compile for libfb

Code: Select all

gcc -c -o libfb.o libfb.c -mtune=native -Wall -pipe -O3 -g -I../../include/ -fPIC -Wall -Wpedantic
gcc -shared -o libfb.so libfb.o
compile for test / main.c

Code: Select all

gcc -o test main.c image.c ../libfb.o -lpng -mtune=native -Wall -pipe -O3 -g -I../../include/ -fPIC -Wall -Wpedantic
Last edited by grininmonkey on Tue Oct 16, 2018 4:37 pm, edited 1 time in total.

grininmonkey
Posts: 92
Joined: Mon Jul 30, 2018 3:44 pm

Re: I am missing some fundamental understanding of C?

Tue Oct 16, 2018 4:32 pm

danjperron wrote:
Tue Oct 16, 2018 3:41 pm
lfb.putpixel this looks like c++ not C.

Please provide the name of the library you are using and the headers info of your source files. The include stuff at the beginning.

I think that you need to pass lfb into your function but since we don't know which libraries or missing function you are using it is hard to figure it out.
Depending on the context... I would get compile errors when using -> member notation vs . notation. Via trial and error I have observed that when I reference a struct's member within the same scope the compiler wants . notation... if not in the same scope or passed as an address of a pointer like in my use in the image.c file... it complains about . notation and suggests "did you mean ->" ...

I don't know if I am doing something wrong... but that's what I get when using gcc ....

jahboater
Posts: 3027
Joined: Wed Feb 04, 2015 6:38 pm

Re: I am missing some fundamental understanding of C?

Tue Oct 16, 2018 4:54 pm

grininmonkey wrote:
Tue Oct 16, 2018 4:32 pm
Depending on the context... I would get compile errors when using -> member notation vs . notation. Via trial and error I have observed that when I reference a struct's member within the same scope the compiler wants . notation... if not in the same scope or passed as an address of a pointer like in my use in the image.c file... it complains about . notation and suggests "did you mean ->" ...

I don't know if I am doing something wrong... but that's what I get when using gcc ....
I think I would get a basic text book on C, or some other learning resource, and try to fully understand how to access structures.
It is quite simple - and then "trial and error" will be in the past!

struct xxx foo;
struct xxx *ptr = &foo;

foo.yyy; // directly access struct field

or

ptr->yyy; // access struct field through the pointer

perhaps remember the -> looks like a "pointer" :)

grininmonkey
Posts: 92
Joined: Mon Jul 30, 2018 3:44 pm

Re: I am missing some fundamental understanding of C?

Tue Oct 16, 2018 5:12 pm

ericcooper wrote:
Tue Oct 16, 2018 3:28 pm
I can't tell what's wrong without seeing more of the code (definition of the Image struct, declaration of the lfb variable), but I'd suggest running your program under the debugger, gdb. (You'll have to compile your code with the -g flag.) Then you can inspect the values of variables when the fault occurs, etc.
I'll need to google some on how to use gdb more.... I only figured out the flag.. and how to run at this point...

the following is what I get when I un-comment my image_render() function and comment out the iteration within main....

Code: Select all

(gdb) run
Starting program : /home/gmonkey/Projects/C/fallout-fb-console/src/fbui/test

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7e31f41 in free () from /usr/lib/libc.so.6
(gdb)

grininmonkey
Posts: 92
Joined: Mon Jul 30, 2018 3:44 pm

Re: I am missing some fundamental understanding of C?

Tue Oct 16, 2018 6:45 pm

Found the issue.... but just don't understand what is happening in terms of behavior ... not the resolution.

The fix is explicit assignment of the allocated flag

Code: Select all

	Image test;
	test.allocated=1;  // <-- this fixes it 
	test.xoffset = 400;
	test.yoffset = 40;
	
	image_load_png(&test,"/home/gmonkey/Projects/C/fallout-fb-console/src/fbui/assets/terminal_test.png");
        image_render(&test);

	/* for (int y=0; y < test.height; y++) */
	/* 	for (int x=0; x < test.width; x++) */
	/* 		lfb.putpixel(x+test.xoffset,y+test.yoffset,test.data[x][y]); */

	image_free(&test);

So after quickly learning how to set break points and use gdb a little more... I quickly spotted the issue... but don't understand how its getting the values it does depending on what is happening further down the instruction set...

Within the image_load_png function I have a section which checks the allocated variable ( if > 1 ) to determine rather or not to free the data member before calloc`ing it based on passed image dimensions.

If I comment out the call to image_render(), the default value is always 1 at the step within the image_load_png function that is evaluating it...

But when I have a call "after" the call to image_load_png that passes a pointer to the same struct object.... the default value when being evaluated at the first function call... image_load_png... is a random high number... for example : 1614676752 which then steps into the call to free the data member which (in this example) has yet to have been calloc`ed.

I now understand I should initialize an expected value... but don't understand how the default value is changed depending on the number of references ?

So just would like to confirm that is expected behavior and I can move on.... or rather or not there might be something deeper that I need to understand to avoid cursing at the screen needlessly ?

danjperron
Posts: 3072
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: I am missing some fundamental understanding of C?

Tue Oct 16, 2018 7:28 pm

I found few bugs in your code that you should fix and there is other also.


1- I got a problem with your image_load_png() function. I found out that it try to free memory when they are NULL pointer.
I fix the problem by modifying

Code: Select all

void image_free(Image *image)
{
  if(image !=NULL)
        if(image->data !=NULL)
       {
        for(int i=0;i<image->height;i++)
             if(image->data[i] != NULL)
               {
                free(image->data[i]);
                image->data[i]=NULL;
               }
        free(image->data);
        image->data=NULL;
       }
}
2- Also your putpixel crash when the x,y dimension are outside the buffer image. Some check has to be include there.


The lfb structure works fine but you need to work on some functions to prevent outside access.

Code: Select all

if(offset > lfb.width * lfb.height) return;
...
...
 if(offset > lfb.width * lfb.height) offset = lfb.width * lfb.height;
it should be

Code: Select all

if(offset >= lfb.width * lfb.height) return;
...
...
 if(offset >= lfb.width * lfb.height) offset = lfb.width * lfb.height-1;

Code: Select all

Width :  441 Height : 951
...
...
lfb_set_pixel32(1733237,0)
putPixel(438,950,0)
lfb_set_pixel32(1733238,0)
putPixel(439,950,0)
lfb_set_pixel32(1733239,0)
putPixel(440,950,0)
lfb_set_pixel32(1733240,0)
Erreur de segmentation

grininmonkey
Posts: 92
Joined: Mon Jul 30, 2018 3:44 pm

Re: I am missing some fundamental understanding of C?

Tue Oct 16, 2018 8:04 pm

danjperron wrote:
Tue Oct 16, 2018 7:28 pm
I found few bugs in your code that you should fix and there is other also.

. . . . . .
Updated what you pointed out... thanks!

User avatar
Paeryn
Posts: 2169
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: I am missing some fundamental understanding of C?

Tue Oct 16, 2018 9:52 pm

danjperron wrote:
Tue Oct 16, 2018 7:28 pm
1- I got a problem with your image_load_png() function. I found out that it try to free memory when they are NULL pointer.
Calling free() with a null pointer isn't a problem otherwise the compiler's standard library implementation doesn't conform to the standard.

free() is explicitly defined as to do nothing if passed NULL so it is perfectly safe.
She who travels light — forgot something.

danjperron
Posts: 3072
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: I am missing some fundamental understanding of C?

Tue Oct 16, 2018 10:40 pm

free() is explicitly defined as to do nothing if passed NULL so it is perfectly safe.

Yes of course but
calling image->data when image is NULL is a big problem!

Hey I learned C using CP/M on a Osborne portable computer with floppy disk. At that time you have to be aware of everything. So it is an habit to be sure that everything it is ok before doing anything .

Return to “C/C++”