0

I was modifying code from a project someone had finished with an ASCII art torus, known as donut.c. I felt compelled to draw other three dimensional shapes with the code from this program in an object-oriented paradigm, but also wanted to modify it to let it run on multiple platforms. I chose to use C++ with ncurses so that the library could be used on Windows, Linux, and Mac. However, I am running into an error with my code: a segmentation fault occurs at a very specific part of my code consistently, and I don't know where to move forward on fixing the issue.

I take the code (found below) and compile it using g++ -Wall -g test.cc -o test -lncurses so we can use gdb to find out where the issue is. Here is the output of that encounter:

(gdb) watch test == 3030
Hardware watchpoint 1: test == 3030
(gdb) r
Hardware watchpoint 1: test == 3030

Old value = 0
New value = 1
main (argc=1, argv=0xbffff1d4) at test.cc:38
38          Output(output, screen_height, screen_width);
(gdb) step
Output (
  output=0xbfffe958 ' ' <repeats 28 times>, "$$@@@@@@", '$' <repeats 15 times>, ' ' <repeats 54 times>, '$' <repeats 11 times>, '#' <repeats 13 times>, "$$$##", ' ' <repeats 48 times>, "##$$$$#$####******"..., screen_height=24, 
screen_width=80) at test.cc:91
91        printw(output)
(gdb) step
Program received signal SIGSEGV, Segmentation fault.
__wcslen_sse2 () at ../sysdeps/i386/i686/multiarch/wcslen-sse2.S:28
28      ../sysdeps/i386/i686/multiarch/wcslen-sse2.S: No such file or directory.

The test variable is set up to the point to where I know at the 3030th frame, it will fault out. Interestingly enough, if the screen_width and screen_height value changes, the "frame" at which the segmentation fault happens is still the same. I believe my ncurses library is up to date, as I installed it specifically to work with this project (February 1st 2017).

Here is my C++ code, modified from the original donut.c and redacted to fit only code that is deemed pertinent.

static volatile int test = 0; //used for checking what frame it happened at

void Output(char* output, int screen_height, int screen_width); //where segfault happens
void RenderFrame(float x_rotation, float z_rotation, char* output, float* zbuffer, int screen_height, int screen_width);

int main(int argc, const char **argv)
{ 
  //Initialization completed. Note that I call initscr() and necessary methods before
  while(getch() == ERR)
  {
    RenderFrame(x_rotation, z_rotation, output, zbuffer, screen_height, screen_width);
    test++;
    Output(output, screen_height, screen_width);
    x_rotation += x_rotation_delta;
    z_rotation += z_rotation_delta;
  }
  endwin();

  return 0;
}

void Output(char* output, int screen_height, int screen_width)
{
  printw(output);
  refresh();
  move(0, 0);
}

TL;DR

ncurses has an issue with printw that causes a Segmentation fault. How do I fix this issue or move around it so that I can get this to work correctly. More so, is it an issue with ncurses or my code?

Community
  • 1
  • 1
astrogeek14
  • 234
  • 1
  • 14
  • In `RenderFrame` it looks relatively easy to push `index` out of bounds with a rectangular screen. Guard against that and see if your problem with `printw` goes away. If it doesn't, at least you've squashed one bug. – user4581301 Feb 06 '17 at 00:25
  • 2
    valgrind is useful for finding bugs like this (it's unlikely to be a bug in ncurses). By the way, `addstr` is better suited to the use you're making than `printw` (a stray `%` will do bad things with your code). – Thomas Dickey Feb 06 '17 at 00:46
  • `float zbuffer[screen_width * screen_height]` -- This line and lines like this are not valid C++. If you used `std::vector` instead, you could, at the very least, check to ensure all access to the vector are within bounds using `at()`. – PaulMcKenzie Feb 06 '17 at 01:07
  • In addition, `for(theta = 0; theta < 2 * M_PI; theta += theta_spacing)` -- A `for` loop that uses floating point variables like this is not guaranteed to run the same number of times, due to floating point being an approximation. Change compiler options, and your loop may run one time less (or too many) than what you expect. The same goes for any calculation that uses floating point, and expect it to give consistent results such as `xp = (int)(screen_width / 2 + K1 * ooz * x);` ...`yp = (int)(screen_height / 2 - K1 / 2 * ooz * y);` – PaulMcKenzie Feb 06 '17 at 01:10
  • 2
    Please don't post whole programs that you need fixed. Minimize your issue to a [MCVE](http://stackoverflow.com/help/mcve) and ask a specific question. – cubuspl42 Feb 06 '17 at 01:47
  • I redacted the code to only fit size necessary, thank you for the update. – astrogeek14 Feb 06 '17 at 04:02

1 Answers1

0

The issue was as Thomas Dickey described in his comment to the question: I needed to change printw to addstr in the code. Thank you all for your suggestions, and I'm still curious as to why this happens with printw.

Community
  • 1
  • 1
astrogeek14
  • 234
  • 1
  • 14