View previous topic :: View next topic |
Author |
Message |
LoTeK Apprentice
Joined: 26 Jul 2012 Posts: 270
|
Posted: Sat Jan 19, 2013 12:07 am Post subject: gtk+ cairo --> segmentation fault |
|
|
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 |
|
|
derk Guru
Joined: 10 Mar 2003 Posts: 347 Location: St Thomas Ontario
|
Posted: Sat Jan 19, 2013 2:14 am Post subject: |
|
|
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 |
|
|
VoidMage Watchman
Joined: 14 Oct 2006 Posts: 6196
|
Posted: Sat Jan 19, 2013 3:48 am Post subject: |
|
|
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 |
|
|
wcg Guru
Joined: 06 Jan 2009 Posts: 588
|
Posted: Sat Jan 19, 2013 8:14 am Post subject: |
|
|
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 |
|
|
VoidMage Watchman
Joined: 14 Oct 2006 Posts: 6196
|
Posted: Sat Jan 19, 2013 2:37 pm Post subject: |
|
|
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 |
|
|
LoTeK Apprentice
Joined: 26 Jul 2012 Posts: 270
|
Posted: Sat Jan 19, 2013 5:30 pm Post subject: |
|
|
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 ? |
|
Back to top |
|
|
VoidMage Watchman
Joined: 14 Oct 2006 Posts: 6196
|
Posted: Sat Jan 19, 2013 6:50 pm Post subject: |
|
|
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 |
|
|
BillWho Veteran
Joined: 03 Mar 2012 Posts: 1600 Location: US
|
Posted: Sun Jan 20, 2013 2:01 am Post subject: |
|
|
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
Since installing gentoo, my life has become one long emerge |
|
Back to top |
|
|
wcg Guru
Joined: 06 Jan 2009 Posts: 588
|
Posted: Sun Jan 20, 2013 5:53 am Post subject: |
|
|
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 |
|
|
LoTeK Apprentice
Joined: 26 Jul 2012 Posts: 270
|
Posted: Sun Jan 20, 2013 10:45 pm Post subject: |
|
|
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 |
|
|
VoidMage Watchman
Joined: 14 Oct 2006 Posts: 6196
|
Posted: Mon Jan 21, 2013 7:14 am Post subject: |
|
|
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 |
|
|
wcg Guru
Joined: 06 Jan 2009 Posts: 588
|
Posted: Mon Jan 21, 2013 7:35 am Post subject: |
|
|
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 |
|
|
wcg Guru
Joined: 06 Jan 2009 Posts: 588
|
Posted: Mon Jan 21, 2013 7:50 am Post subject: |
|
|
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 |
|
|
|
|
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
|
|