Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > segmentation fault sometimes

Reply
Thread Tools

segmentation fault sometimes

 
 
Ken
Guest
Posts: n/a
 
      09-10-2009
Hi,

I have a little program running on Linux to draw a status bar with
framebuffer, but it has segment fault after it is run several times,
first time is ok usually, 2nd, 3rd times it produces segmentation
fault core dump, it is caused by the line below, could anyone help how
to fix the issue?

*(fbp + location) = 255; /* has segmentation fault sometimes here */

---------------------------------------------------------------
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <stdlib.h>

inline static unsigned short int make16color(unsigned char r, unsigned
char g, unsigned char b)
{
return (
(((r >> 3) & 31) << 11) |
(((g >> 2) & 63) << 5) |
((b >> 3) & 31) );
}

int main(void) {
int fbfd = 0;
struct fb_var_screeninfo vinfo =
{ .xres=0, .yres=0, .bits_per_pixel=0,
.xoffset=0, .yoffset=0 };
struct fb_fix_screeninfo finfo = { .line_length=0 };
long int screensize = 0;
char *fbp = 0;
unsigned x = 0, y = 0;
int guage_height = 20, step = 10;
unsigned int location = 0;

// Open the file for reading and writing
fbfd = open("/dev/fb0", O_RDWR);
if (!fbfd) {
printf("Error: cannot open framebuffer device.\n");
exit(1);
}
printf("The framebuffer device was opened successfully.\n");

// Get fixed screen information
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {
printf("Error reading fixed information.\n");
exit(2);
}

// Get variable screen information
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
printf("Error reading variable information.\n");
exit(3);
}
// Figure out the size of the screen in bytes
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;

// Map the device to memory
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE,
MAP_SHARED,
fbfd, 0);

if ((int)fbp == -1) {
printf("Error: failed to map framebuffer device to memory.
\n");
exit(4);
}
printf("The framebuffer device was mapped to memory successfully.
\n");

//set to black color first
memset(fbp, 0, screensize);
//draw rectangle
y = (vinfo.yres - guage_height) / 2 - 2; // Where we are
going to put the pixel

for (x = step - 2; x < vinfo.xres - step + 2; x++) {
location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/ +
(y+vinfo.yoffset) * finfo.line_length;
*(fbp + location) = 255; /* has segmentation fault sometimes
here */
}

y = (vinfo.yres + guage_height) / 2 + 2; // Where we are
going to put the pixel
for (x = step - 2; x < vinfo.xres - step + 2; x++) {
location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/ +
(y+vinfo.yoffset) * finfo.line_length;
*(fbp + location) = 255;
}

x = step - 2;
for (y = (vinfo.yres - guage_height) / 2 - 2; y < (vinfo.yres +
guage_height) / 2 + 2; y++) {
location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/ +
(y+vinfo.yoffset) * finfo.line_length;

*(fbp + location) = 255;
}

x = vinfo.xres - step + 2;
for (y = (vinfo.yres - guage_height) / 2 - 2; y < (vinfo.yres +
guage_height) / 2 + 2; y++) {
location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/ +
(y+vinfo.yoffset) * finfo.line_length;

*(fbp + location) = 255;
}

// Figure out where in memory to put the pixel
for ( x = step; x < vinfo.xres - step; x++ ) {
for ( y = (vinfo.yres - guage_height) / 2; y < (vinfo.yres +
guage_height) / 2; y++ ) {
location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/ +
(y+vinfo.yoffset) * finfo.line_length;

if ( vinfo.bits_per_pixel == 32 ) {
*(fbp + location) = 100; // Some blue
*(fbp + location + 1) = 15+(x-100)/2; // A little
green
*(fbp + location + 2) = 200-(y-100)/5; // A lot of
red
*(fbp + location + 3) = 0; // No transparency
} else { //assume 16bpp
unsigned char b = 255 * x / (vinfo.xres - step);
unsigned char g = 255; // (x - 100)/6 A little
green
unsigned char r = 255; // A lot of red
unsigned short int t = make16color(r, g, b);
*((unsigned short int*)(fbp + location)) = t;
}
}
usleep(200);
}
//clean framebuffer
munmap(fbp, screensize);
close(fbfd);

return 0;
}
---------------------------------------------------------------
 
Reply With Quote
 
 
 
 
Kenny McCormack
Guest
Posts: n/a
 
      09-10-2009
In article <(E-Mail Removed)>,
Ken <(E-Mail Removed)> wrote:
>Hi,
>
>I have a little program running on Linux to draw a status bar with
>framebuffer, but it has segment fault after it is run several times,
>first time is ok usually, 2nd, 3rd times it produces segmentation
>fault core dump, it is caused by the line below, could anyone help how
>to fix the issue?


The fact is, nobody here gives a **** about you or your problems.

You may find some or all of the following links helpful in understanding
why this is so:

http://en.wikipedia.org/wiki/Aspergers
http://en.wikipedia.org/wiki/Clique
http://en.wikipedia.org/wiki/C_programming_language

 
Reply With Quote
 
 
 
 
David Resnick
Guest
Posts: n/a
 
      09-10-2009
On Sep 9, 11:43*pm, Ken <(E-Mail Removed)> wrote:
> Hi,
>
> I have a little program running on Linux to draw a status bar with
> framebuffer, but it has segment fault after it is run several times,
> first time is ok usually, 2nd, 3rd times it produces segmentation
> fault core dump, it is caused by the line below, could anyone help how
> to fix the issue?
>


A few suggestions:
1) Valgrind is often very helpful for debugging memory corruption
issues on linux. This can in general just tell you what is wrong.
I'm not sure however it is as good with mmap'd memory as it is with
*alloc memory.

2) You could add either printfs or run under the debugger depending on
your tastes for such. Displaying by some means the various fbp and
location values prior to de-referencing will probably help you. Maybe
location is unexpectedly calculated to a bigger size than screensize?

-David
 
Reply With Quote
 
Ken
Guest
Posts: n/a
 
      09-11-2009
On Sep 10, 6:16*pm, Richard Heathfield <(E-Mail Removed)> wrote:
> In <(E-Mail Removed)>,
>
> Ken wrote:
> > Hi,

>
> > I have a little program running on Linux to draw a status bar with
> > framebuffer, but it has segment fault after it is run several times,
> > first time is ok usually, 2nd, 3rd times it produces segmentation
> > fault core dump, it is caused by the line below, could anyone help
> > how to fix the issue?

>
> > *(fbp + location) = 255; /* has segmentation fault sometimes here */

>
> Idiomatically, this can be written as fbp[location] = 255, and this


I changed it to fbp[location] = 255, thanks.

> may give you a clue as to what is probably going wrong. The fbp
> pointer represents an address in memory. It is of type char *, so any
> addition to it (say, + n) results in another address, n bytes further
> on in memory. If your program "owns" all the addresses in between,
> you're fine. You're not fine, and therefore we may conclude that you
> don't own all those addresses. The obvious candidate is location,
> which is calculated immediately prior to your segfault.
>
> * location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/ +
> * * * * * * * * *(y+vinfo.yoffset) * finfo.line_length;
>
> In your position, I would start off my debugging efforts by writing
> some trace code that dumps values like x, vinfo.xoffset,
> vinfo.bits_per_pixel/8, etc etc, to a file, all neatly labelled so
> that you know what they are - and make sure the file is fflushed
> before you move to the sometimes-segfaulting line. I think you'll
> discover on examining the file that the result calculated and
> assigned to location is screwed (either completely way out and
> obvious, or perhaps more subtle, maybe just an off-by-one error in
> one or more of the inputs to that calculation).


These values are fixed to a specific video card.
screensize=307200, vinfo.bits_per_pixel/8= 2, finfo.line_length=960,
vinfo.xres = 480,
when it is normal and there is no segment fault error, the location
is : min=142096 max=143022,
when segment fault happens, the following values are,

(x,y), (vinfo.xoffset,vinfo.yoffset), location
(8, 14, (0, 320), 449296

I still don't figure out the root cause till now why it access memory
out of the program.

>
> On a final note: despite all appearances to the contrary, your
> question was topical here. It was not immediately obvious, however,
> that this was the case, so don't be surprised if you get a few
> kneejerk replies along the lines of "you're off-topic, go to a Linux
> group".
>
> --
> Richard Heathfield <http://www.cpax.org.uk>
> Email: -http://www. +rjh@
> "Usenet is a strange place" - dmr 29 July 1999
> Sig line vacant - apply within


 
Reply With Quote
 
Alan Curry
Guest
Posts: n/a
 
      09-11-2009
In article <(E-Mail Removed)>,
Ken <(E-Mail Removed)> wrote:
>
>These values are fixed to a specific video card.
>screensize=307200, vinfo.bits_per_pixel/8= 2, finfo.line_length=960,
>vinfo.xres = 480,
>when it is normal and there is no segment fault error, the location
>is : min=142096 max=143022,
>when segment fault happens, the following values are,
>
>(x,y), (vinfo.xoffset,vinfo.yoffset), location
>(8, 14, (0, 320), 449296
>
>I still don't figure out the root cause till now why it access memory
>out of the program.


It looks like the yoffset is causing your trouble. Before going into detail,
a preliminary question about the code.

Given an (x,y) coordinate pair, you have used this formula to calculate an
offset into the fb memory:

location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/ +
(y+vinfo.yoffset) * finfo.line_length;

Did you write that code yourself or copy it from somewhere? Can you explain
what all the terms mean? I suspect you copied it and haven't actually found
out what the xoffset and yoffset are for.

I didn't know what they were for either, a few minutes ago. Documentation on
the fb ioctls is too hard to find. But I think I've got it figured out:
xoffset and yoffset are the offset from beginning of fb memory to the first
visible pixel.

You've got a lot more video RAM than you'd need to store a screenful of
pixels at this resolution (by the way, 480 pixels horizontal? what a weird
number). The fb driver is providing you a virtual screen that is bigger than
the physical screen. By changing xoffset and yoffset, you can make the screen
scroll smoothly, revealing previously hidden pieces of the virtual screen.

Your location = ... calculation adds xoffset and yoffset to translate the
(x,y) coordinates (taken as relative to the physical screen origin) into a
byte offset (relative to the beginning of fb memory). So the byte offset can
be anywhere within the virtual screen, but the size of your mmap was based on
the physical resolution. You didn't mmap the entire virtual screen.

You should use xres_virtual and yres_virtual when calculating the amount of
memory to map. That would be

screensize =
vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel / 8;

But there's still a bug there. Video modes can have unused padding bytes at
the end of each row of pixels, for alignment purposes. The correct way to
convert "number of rows" to "number of bytes" is to multiply by
finfo.line_length (which you already did in the "location" formula, adding to
my suspicion that you copied that code without understanding it.).

line_length, also called the "stride" of the video mode, will be equal to
vinfo.xres_virtual * vinfo.bits_per_pixel/8 in the normal no-padding case.

The correct mmap size for all cases should be:

screensize = vinfo.yres_virtual * finfo.line_length;

If I've got all that right, there's still an unanswered question - what's
causing yoffset to change between (or during) runs of your program? But maybe
you won't need to answer that.

--
Alan Curry
 
Reply With Quote
 
Ken
Guest
Posts: n/a
 
      09-14-2009
On Sep 11, 6:07 pm, (E-Mail Removed) (Alan Curry) wrote:
> In article <(E-Mail Removed)>,
>
> Ken <(E-Mail Removed)> wrote:
>
> >These values are fixed to a specific video card.
> >screensize=307200, vinfo.bits_per_pixel/8= 2, finfo.line_length=960,
> >vinfo.xres = 480,
> >when it is normal and there is no segment fault error, the location
> >is : min=142096 max=143022,
> >when segment fault happens, the following values are,

>
> >(x,y), (vinfo.xoffset,vinfo.yoffset), location
> >(8, 14, (0, 320), 449296

>
> >I still don't figure out the root cause till now why it access memory
> >out of the program.

>
> It looks like the yoffset is causing your trouble. Before going into detail,
> a preliminary question about the code.
>
> Given an (x,y) coordinate pair, you have used this formula to calculate an
> offset into the fb memory:
>
> location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/ +
> (y+vinfo.yoffset) * finfo.line_length;
>
> Did you write that code yourself or copy it from somewhere? Can you explain
> what all the terms mean? I suspect you copied it and haven't actually found
> out what the xoffset and yoffset are for.
>
> I didn't know what they were for either, a few minutes ago. Documentation on
> the fb ioctls is too hard to find. But I think I've got it figured out:
> xoffset and yoffset are the offset from beginning of fb memory to the first
> visible pixel.
>
> You've got a lot more video RAM than you'd need to store a screenful of
> pixels at this resolution (by the way, 480 pixels horizontal? what a weird
> number). The fb driver is providing you a virtual screen that is bigger than
> the physical screen. By changing xoffset and yoffset, you can make the screen
> scroll smoothly, revealing previously hidden pieces of the virtual screen.
>
> Your location = ... calculation adds xoffset and yoffset to translate the
> (x,y) coordinates (taken as relative to the physical screen origin) into a
> byte offset (relative to the beginning of fb memory). So the byte offset can
> be anywhere within the virtual screen, but the size of your mmap was based on
> the physical resolution. You didn't mmap the entire virtual screen.
>
> You should use xres_virtual and yres_virtual when calculating the amount of
> memory to map. That would be
>
> screensize =
> vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel / 8;
>
> But there's still a bug there. Video modes can have unused padding bytes at
> the end of each row of pixels, for alignment purposes. The correct way to
> convert "number of rows" to "number of bytes" is to multiply by
> finfo.line_length (which you already did in the "location" formula, adding to
> my suspicion that you copied that code without understanding it.).


Yes are right, I copied the code from some elsewhere post on Internet
and added minor change to correct bugs, I'd just play with this
program and learn from it, but the segment fault bug needs the expert
help in this group.

>
> line_length, also called the "stride" of the video mode, will be equal to
> vinfo.xres_virtual * vinfo.bits_per_pixel/8 in the normal no-padding case.
>
> The correct mmap size for all cases should be:
>
> screensize = vinfo.yres_virtual * finfo.line_length;


This fixed the segment fault bug here eventually, I learn from the
struct fb_fix_screeninfo actually the screen size is finfo.smem_len,
so instead of calculating it, just using smem_len is ok, I also
verified, your fixed screensize equals to the smem_len.

Another on-topic question is,
We can write *(fbp + location) = 255; as fbp[location] = 255; per the
suggestion in the thread.
how to rewrite below statement?
((unsigned short int*)(fbp+location)) = t;
If I rewrite it to fbp[location] = t, then I'll get wrong result.

>
> If I've got all that right, there's still an unanswered question - what's
> causing yoffset to change between (or during) runs of your program? But maybe
> you won't need to answer that.


This is what I can not answer as you may see it, I also don't know why
it is changed between several runs, it is set to zero during
initialization in fact.
struct fb_var_screeninfo vinfo =
{ .xres=0, .yres=0, .bits_per_pixel=0,
.xoffset=0, .yoffset=0 };

>
> --
> Alan Curry


 
Reply With Quote
 
Alan Curry
Guest
Posts: n/a
 
      09-14-2009
In article <(E-Mail Removed)>,
Ken <(E-Mail Removed)> wrote:
>On Sep 11, 6:07 pm, (E-Mail Removed) (Alan Curry) wrote:
>> In article

>
>Another on-topic question is,
>We can write *(fbp + location) = 255; as fbp[location] = 255; per the
>suggestion in the thread.
>how to rewrite below statement?
>((unsigned short int*)(fbp+location)) = t;
>If I rewrite it to fbp[location] = t, then I'll get wrong result.


That won't easily translate to array syntax because of the mixed pointer
types. You have a pointer that is mismatched to the actual underlying
hardware data format, but you have a great excuse: the actual underlying
hardware data format is not known until runtime. There's gotta be a
conversion somewhere. The cast is justified. You could hide the addition by
translating fbp+location into &fbp[location] but I wouldn't consider that an
improvement.

>
>>
>> If I've got all that right, there's still an unanswered question - what's
>> causing yoffset to change between (or during) runs of your program? But maybe
>> you won't need to answer that.

>
>This is what I can not answer as you may see it, I also don't know why
>it is changed between several runs, it is set to zero during
>initialization in fact.
> struct fb_var_screeninfo vinfo =
>{ .xres=0, .yres=0, .bits_per_pixel=0,
> .xoffset=0, .yoffset=0 };


Those initial values have no effect because you didn't send them to the
kernel (with a PUT ioctl). Your first GET ioctl overwrote them. All those
pretty 0's were never used.

--
Alan Curry
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
OT: I find... sometimes it's easy to be myself... sometimes... I find it's better to be somebody else. The Obelisk [7.13.86.42] MCSE 10 06-04-2006 05:40 AM
Firefox locks up on first URL sometimes; Sometimes closes itself Jim Firefox 0 06-28-2005 01:42 PM
? Content Entered in Forms Sometimes Duplicated and Sometimes Not ? Nehmo Sergheyev HTML 1 05-09-2004 07:07 PM
::std sometimes needed, sometimes not Marcin Vorbrodt C++ 24 09-17-2003 03:01 PM
Re: Sometimes ASP.NET does find the dll, sometimes doesn't John Saunders ASP .Net 0 08-28-2003 01:40 PM



Advertisments