Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
gtk+ cairo --> segmentation fault
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Portage & Programming
View previous topic :: View next topic  
Author Message
LoTeK
Apprentice
Apprentice


Joined: 26 Jul 2012
Posts: 270

PostPosted: Sat Jan 19, 2013 12:07 am    Post subject: gtk+ cairo --> segmentation fault Reply with quote

hi,
Although this forum is also about basic programming questions, I'm not sure if my question is either basic enough or to far away from gentoo or the C core language, but anyway I'll ask :)

I've written a program that displays the power usage, temperature and charge status of my battery and if AC is online or not (through pictures), and it works fine but after maybe 5 mins the program suddenly crashes with "Segmentation fault" to stderr.
I think "segmentation fault" means that the program tries to access some parts of the RAM that it isn't allowed to?! but because the program runs correct for few minutes I don't know where my fault could be...

here is my code:
http://bpaste.net/show/71273

btw, I also think that it's rather poorly coded (I'm new to graphic-programming), so if anyone has suggestions to program anything better although it's not connected to the problem I'm happy to read from you... :)
Back to top
View user's profile Send private message
derk
Guru
Guru


Joined: 10 Mar 2003
Posts: 347
Location: St Thomas Ontario

PostPosted: Sat Jan 19, 2013 2:14 am    Post subject: Reply with quote

static gboolean time_handler (GtkWidget *widget)
{
if (widget == NULL)
return FALSE;
# I think your problem is here
# do the fopen (s) once only to get the handle (s) then you do the fscanf on the same handle when you need fresh data
# other wise I think you run out of file handles especially as you over write them without releasing them (i.e. fclose) thus crash
# file handles are a finite system resource :^)

power_file = fopen ("/sys/devices/platform/smapi/BAT0/power_now", "r");
fscanf (power_file, "%i", &power);

perc_file = fopen ("/sys/devices/platform/smapi/BAT0/remaining_percent", "r");
fscanf (perc_file, "%i", &perc);

temp_file = fopen ("/sys/devices/platform/smapi/BAT0/temperature", "r");
fscanf (temp_file, "%i", &temp);

update_squares (power);
update_temp (temp);
update_perc (perc);

gtk_widget_queue_draw (widget);
return TRUE;
}
Back to top
View user's profile Send private message
VoidMage
Watchman
Watchman


Joined: 14 Oct 2006
Posts: 6196

PostPosted: Sat Jan 19, 2013 3:48 am    Post subject: Reply with quote

While the above might be a reason too (as you're leaking the descriptors right and left), there's one other thing.

In gtk3, for the widgets you're using, you shouldn't use gdk_cairo_create...cairo_destroy in 'draw' callbacks.
You're getting the context as a parameter and it must not be destroyed.

On a not quite related note, is there any point of using GtkFixed here ?
Back to top
View user's profile Send private message
wcg
Guru
Guru


Joined: 06 Jan 2009
Posts: 588

PostPosted: Sat Jan 19, 2013 8:14 am    Post subject: Reply with quote

The other comments aside, what is a segfault? It is writing into
address space not allocated to your program. You can get it by
somehow corrupting an address assigned to a variable, then
writing to that variable, or by simply overrunning a buffer that
is close enough to a boundary of space allocated to your program
that the write extends into something else's address space
or into unallocated address space (either way, the kernel
knows this address space is not allocated to your process).

That could happen due to a bug in gtk or in some other
shared library that your process calls, but more commonly
the bug is in your own code.

If you can start the process from a terminal window, you
can use gdb in that terminal window to start the process
and get a backtrace of the sequence of function calls
with their arguments that leads to the segfault.

http://www.gentoo.org/proj/en/qa/backtraces.xml

(Recompiling the system with -ggdb in CFLAGS and
FEATURES=splitdebug in /etc/portage/make.conf
will get you better information from gdb. Typically
the only cost is disk space for the debug information
from programs and libraries.)
_________________
TIA
Back to top
View user's profile Send private message
VoidMage
Watchman
Watchman


Joined: 14 Oct 2006
Posts: 6196

PostPosted: Sat Jan 19, 2013 2:37 pm    Post subject: Reply with quote

Regarding above: while usually it only costs disk space, sometimes it costs a lot of it - i.e. in cases like firefox, it's (IRC) about 8x the size and in the case of webkit-gtk, the memory/disk space consumption during build is a bit crazy.
Back to top
View user's profile Send private message
LoTeK
Apprentice
Apprentice


Joined: 26 Jul 2012
Posts: 270

PostPosted: Sat Jan 19, 2013 5:30 pm    Post subject: Reply with quote

derk wrote:
static gboolean time_handler (GtkWidget *widget)
{
if (widget == NULL)
return FALSE;
# I think your problem is here
# do the fopen (s) once only to get the handle (s) then you do the fscanf on the same handle when you need fresh data
# other wise I think you run out of file handles especially as you over write them without releasing them (i.e. fclose) thus crash
# file handles are a finite system resource :^)

power_file = fopen ("/sys/devices/platform/smapi/BAT0/power_now", "r");
fscanf (power_file, "%i", &power);

perc_file = fopen ("/sys/devices/platform/smapi/BAT0/remaining_percent", "r");
fscanf (perc_file, "%i", &perc);

temp_file = fopen ("/sys/devices/platform/smapi/BAT0/temperature", "r");
fscanf (temp_file, "%i", &temp);

update_squares (power);
update_temp (temp);
update_perc (perc);

gtk_widget_queue_draw (widget);
return TRUE;
}


I've added after each fscanf-* line a fclose (*_file) line and now the program doesn't crashes..!! before that I've initiate each file in the main function and after that in the gtk-main function and then the fscanf's were always the same, why? my files are global variables and initiated, why can fscanf in the time_handler not read the new values?

Quote:
While the above might be a reason too (as you're leaking the descriptors right and left), there's one other thing.

What are descriptors?

Quote:
In gtk3, for the widgets you're using, you shouldn't use gdk_cairo_create...cairo_destroy in 'draw' callbacks.
You're getting the context as a parameter and it must not be destroyed.


I have the function from this tutorial http://zetcode.com/gfx/cairo/cairobackends/.
This is maybe related to my question above, because once I've declared "cairo_t *cr;" in my main-function but than I've had a segmentation fault too, so I did it with multiple contexts. How else should I create the cairo context?

Quote:
On a not quite related note, is there any point of using GtkFixed here ?

Because AFAIK it's not possible to add more than one widget to the main-window, so I've added GtkFixed as a container for the other three drawing areas, is this not good?
Another way was to add only one drawing area to the main-window, but then it's more painful to position the picture and the drawings.

@wcg
thanks, despite this problem I want to start using gdb! I've set the FEATURES, CFLAGS, should I'll recompile with
Code:
emerge -e world
?
Back to top
View user's profile Send private message
VoidMage
Watchman
Watchman


Joined: 14 Oct 2006
Posts: 6196

PostPosted: Sat Jan 19, 2013 6:50 pm    Post subject: Reply with quote

Looks like that guide is simply not quite correct - unless you're using widgets like GtkLayout (which beside its standard GdkWindow has another for the scrolled content (_get_bin_window)), the only context that matters (besides the ones you want to create) is the one you get in that callback parameter.
As for the other question: 'man fopen', 'man fclose'.

Regarding GtkFixed: use a GtkGrid then; GtkFixed is really not a good idea.
Back to top
View user's profile Send private message
BillWho
Veteran
Veteran


Joined: 03 Mar 2012
Posts: 1600
Location: US

PostPosted: Sun Jan 20, 2013 2:01 am    Post subject: Reply with quote

LoTeK wrote:
I've added after each fscanf-* line a fclose (*_file) line and now the program doesn't crashes..!! before that I've initiate each file in the main function and after that in the gtk-main function and then the fscanf's were always the same, why? my files are global variables and initiated, why can fscanf in the time_handler not read the new values?


It's been a long time since I did any c or c++ programming, but to answer your question you probably hit the EOF after your initial read so all subsequent read attempts would error and return nothing to the buffer leaving the previous contents intact.

You wouldn't realize this, just like running out of file handles, because you're not doing any error checking.

Try a fseek(stream, 0L, SEEK_SET) or rewind(FILE *stream) before each read - either will return the file pointer to the beginning.

Also you might want to open the files similarly to the way I used to:

Code:
void get(void)
{
  int address = 0;
  FILE *p;
  char **msg_ptr;

  if((p=fopen("cmos.dat","w+b")) == NULL) {
     puts("*ERROR* Cannot create CMOS.DAT file");
     exit(-1);
  }

Naturally, you would probably want to do something different with the error.
_________________
Good luck :wink:

Since installing gentoo, my life has become one long emerge :)
Back to top
View user's profile Send private message
wcg
Guru
Guru


Joined: 06 Jan 2009
Posts: 588

PostPosted: Sun Jan 20, 2013 5:53 am    Post subject: Reply with quote

Quote:
emerge -e world

You might want to do
Code:

(emerge -ep world) 2>&1 | tee world.list

first to see what all it wants to re-emerge.

As VoidMage pointed out, this can use a lot of disk space and
memory at compile time, but it only uses extra space at load
time and run time if you are actually running something in gdb.

You can contain it somewhat by only supplying -ggdb in CFLAGS
and FEATURES=splitdebug when emergeing the actual dependencies
of your program (including glibc and gcc, if you look at the complete
dependency tree) and when compiling your program itself.

I do the whole system, because I have the unused disk space and
memory plus swap to do it without space problems, and because
I do not know in advance when I will need a backtrace of some
system infrastructure program. Rather than doing it all in one fell
swoop, I emerged glibc, gcc, binutils, flex, and bison that way,
and then the dependencies of a program that I needed a backtrace
from. Then I just left -ggdb in CFLAGS and FEATURES=splitdebug
in make.conf, and as packages in system and world get updated,
they get emerged with debug information.

But you can do it all at once. I would log the output in case of
unexpected emerge errors.
_________________
TIA
Back to top
View user's profile Send private message
LoTeK
Apprentice
Apprentice


Joined: 26 Jul 2012
Posts: 270

PostPosted: Sun Jan 20, 2013 10:45 pm    Post subject: Reply with quote

Quote:
Regarding GtkFixed: use a GtkGrid then; GtkFixed is really not a good idea.
why?

Quote:
Try a fseek(stream, 0L, SEEK_SET) or rewind(FILE *stream) before each read - either will return the file pointer to the beginning.

Also you might want to open the files similarly to the way I used to:

ok, I'll give it a try tomorrow...

Quote:
As VoidMage pointed out, this can use a lot of disk space and
memory at compile time, but it only uses extra space at load
time and run time if you are actually running something in gdb.

On my laptop I have only 4GB RAM, but if I create a big swap partition it should not be a problem. The disk space is even less a problem, or am I wrong?

world.list:
http://bpaste.net/show/71650
so I'll better wait till tomorrow.. :)
Back to top
View user's profile Send private message
VoidMage
Watchman
Watchman


Joined: 14 Oct 2006
Posts: 6196

PostPosted: Mon Jan 21, 2013 7:14 am    Post subject: Reply with quote

LoTeK wrote:
Quote:
Regarding GtkFixed: use a GtkGrid then; GtkFixed is really not a good idea.
why?

Simply cause GtkFixed is a widget that's sort of broken by design - just read the docs.
Back to top
View user's profile Send private message
wcg
Guru
Guru


Joined: 06 Jan 2009
Posts: 588

PostPosted: Mon Jan 21, 2013 7:35 am    Post subject: Reply with quote

Quote:
On my laptop I have only 4GB RAM, but if I create a big swap partition it should not be a problem. The disk space is even less a problem, or am I wrong?


Right. I have around 2.8 gigs of disk space in use in /usr/lib/debug/.
I can't say for sure how much ram plus swap you might need
in a future that has not happened yet, but with 8gb of ram and
4gb of swap, an emerge has not failed for lack of allocable memory
yet. (In the past, the things to watch out for were runtimes for
functional languages, like scheme, guile, common lisp, etc. If an
emerge was going to run out of memory before the emerge finished,
that would be the kind of emerge that would do it.)

These days, with disk space in such abundance, you just add another
partition or a huge swap file, mkswap, swapon, and restart the last
emerge.
_________________
TIA
Back to top
View user's profile Send private message
wcg
Guru
Guru


Joined: 06 Jan 2009
Posts: 588

PostPosted: Mon Jan 21, 2013 7:50 am    Post subject: Reply with quote

PS: You can get a complete dependency tree for a package that
portage knows about (has an ebuild for) with equery, part of
the gentoolkit package:
[code]
equery g --depth=0 packagename
[/code]
_________________
TIA
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Portage & Programming All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum