Closed z-rui closed 5 years ago
I tried to reproduce the SegFaults error but failed to do so.
Here is the ncurses version information I found on Linux system on which it was developed:
ii libncurses5:amd64 6.1-1ubuntu1.18.04 amd64 shared libraries for terminal handling
ii libncurses5-dev:amd64 6.1-1ubuntu1.18.04 amd64 developer's libraries for ncurses
ii libncursesw5:amd64 6.1-1ubuntu1.18.04 amd64 shared libraries for terminal handling (wide character support)
ii libncursesw5-dev:amd64 6.1-1ubuntu1.18.04 amd64 developer's libraries for ncursesw
ii ncurses-base 6.1-1ubuntu1.18.04 all basic terminal type definitions
ii ncurses-bin 6.1-1ubuntu1.18.04 amd64 terminal-related programs and man pages
ii ncurses-doc 6.1-1ubuntu1.18.04 all developer's guide and documentation for ncurses
I compiled the program under this Linux environment and run it with Valgrind. The program run normally and here is the information emitted by Valgrind after simulation finished:
==28577== Memcheck, a memory error detector
==28577== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==28577== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==28577== Command: ./life
==28577==
==28577==
==28577== HEAP SUMMARY:
==28577== in use at exit: 145,558 bytes in 565 blocks
==28577== total heap usage: 900 allocs, 335 frees, 407,170 bytes allocated
==28577==
==28577== LEAK SUMMARY:
==28577== definitely lost: 96 bytes in 1 blocks
==28577== indirectly lost: 495 bytes in 6 blocks
==28577== possibly lost: 0 bytes in 0 blocks
==28577== still reachable: 144,967 bytes in 558 blocks
==28577== suppressed: 0 bytes in 0 blocks
==28577== Rerun with --leak-check=full to see details of leaked memory
==28577==
==28577== For counts of detected and suppressed errors, rerun with: -v
==28577== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
I cloned the repo. onto another virtual machine which has Ubuntu 16.04 installed. I installed ncurses and glog library by typing:
sudo apt install libncurses5-dev
sudo apt install google-glog-dev
The version information is:
ubuntu 16.04
libgoogle-glog-dev 0.3.4-0.1
libncurses5 6.0+20160213
The program run successfully and the valgrind gave same information.
==14040== Memcheck, a memory error detector
==14040== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==14040== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==14040== Command: ./life
==14040==
==14040==
==14040== HEAP SUMMARY:
==14040== in use at exit: 209,765 bytes in 375 blocks
==14040== total heap usage: 529 allocs, 154 frees, 261,118 bytes allocated
==14040==
==14040== LEAK SUMMARY:
==14040== definitely lost: 0 bytes in 0 blocks
==14040== indirectly lost: 0 bytes in 0 blocks
==14040== possibly lost: 0 bytes in 0 blocks
==14040== still reachable: 209,765 bytes in 375 blocks
==14040== suppressed: 0 bytes in 0 blocks
==14040== Rerun with --leak-check=full to see details of leaked memory
==14040==
==14040== For counts of detected and suppressed errors, rerun with: -v
==14040== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
So far I don't have idea what the problem might be.
Also the definitely lost and indefinitely lost happened when invoking new_item function.
It seems that the ITEM
object didn't get freed correctly, even if I wrapped it inside unique_ptr
.
Attempting to debug this, I explicitly invoked free_item on every ITEM *
in Menu destructor and the return value of free_item function is either -2 or -4. If I used perror after I invoked free_item, it prints "Unknown Error".
After some debugging, the problem seems to be that your call to new_menu
(called by Menu::Menu
by Board::Board
) happened before the call to initscr
(called by Board::SetEnv
).
Before initscr
is called, the global CURRENT_SCREEN
variable in ncurses is NULL, which is in turn used by new_menu
and then caused the segfault.
The problem can be solved by calling initscr
before new_menu
. The following patch works for me:
diff --git a/board.cc b/board.cc
index e53461d..a62c73e 100644
--- a/board.cc
+++ b/board.cc
@@ -99,7 +99,6 @@ void Board::Update(){
}
void Board::SetEnv(){
- initscr();
curs_set(0);
window_ = std::unique_ptr<WINDOW, decltype(&delwin)>(newwin(LINES - 2, COLS - 4, 1,2),&delwin);
getbegyx(window_.get(),min_y_,min_x_);
diff --git a/life.cc b/life.cc
index 23e0d39..ea561aa 100644
--- a/life.cc
+++ b/life.cc
@@ -20,6 +20,7 @@ int main(int argc, char ** argv){
return (EXIT_SUCCESS);
}
try{
+ initscr();
Board bd;
bd.SetEnv();
bd.Run();
though you might want to figure out a more elegant solution.
Just curious about why the SegFault disappears on both of the two machines I experimented on. Does this indicate the behaviour of doing new_menu() before initscr() is nondeterministic?
I appreciate the patch and correction anyway. I will try to come with a more elegant solution.
According to Menus Library documentation, you should initialize ncurses before creating any menus/items. The behavior is quite deterministic, as it always segfaults on my machine.
I suggest that you fix the same problem in the other game your wrote. :)
Compiled with ncurses-6.1 and glog-0.3.4, the program segfaults at program start.
Stack traceback provided by Valgrind is pasted below.
Seems like a problem with the menu library, any idea?