【发布时间】:2017-02-05 22:47:08
【问题描述】:
我正在修改一个项目中的代码,该项目有人使用 ASCII 艺术圆环(称为 donut.c)完成了该项目。我觉得有必要用这个程序的代码在面向对象的范式中绘制其他三维形状,但也想对其进行修改以使其在多个平台上运行。我选择将 C++ 与 ncurses 一起使用,以便该库可以在 Windows、Linux 和 Mac 上使用。但是,我的代码遇到了一个错误:在我的代码的一个非常特定的部分始终出现分段错误,我不知道在哪里解决这个问题。
我获取代码(在下面找到)并使用g++ -Wall -g test.cc -o test -lncurses 对其进行编译,以便我们可以使用gdb 找出问题所在。这是那次遭遇的结果:
(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.
test 变量设置到我知道的第 3030 帧的位置,它会出错。有趣的是,如果screen_width 和screen_height 的值发生变化,发生分段错误的“帧”仍然相同。我相信我的 ncurses 库是最新的,因为我专门安装了它来处理这个项目(2017 年 2 月 1 日)。
这是我的 C++ 代码,从原始的 donut.c 修改并经过编辑以仅适合被认为相关的代码。
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 与printw 存在问题,导致Segmentation fault。我该如何解决这个问题或解决它,以便我可以让它正常工作。更重要的是,ncurses 或我的代码有问题吗?
【问题讨论】:
-
在
RenderFrame中,使用矩形屏幕将index推出边界看起来相对容易。提防这种情况,看看您对printw的问题是否会消失。如果没有,至少你已经解决了一个错误。 -
valgrind 对于发现这样的错误很有用(它不太可能是 ncurses 中的错误)。顺便说一句,
addstr比printw更适合您的用途(流浪的%会对您的代码造成不良影响)。 -
float zbuffer[screen_width * screen_height]-- 这行和类似的行不是有效的 C++。如果您改用std::vector<float>,则至少可以使用at()检查以确保对向量的所有访问都在范围内。 -
此外,
for(theta = 0; theta < 2 * M_PI; theta += theta_spacing)-- 使用这种浮点变量的for循环不能保证运行相同的次数,因为浮点是一个近似值。更改编译器选项,您的循环可能会比您预期的运行时间少(或多)一次。任何使用浮点的计算也是如此,并期望它给出一致的结果,例如xp = (int)(screen_width / 2 + K1 * ooz * x);...yp = (int)(screen_height / 2 - K1 / 2 * ooz * y); -
请不要发布您需要修复的整个程序。将您的问题最小化到MCVE 并提出具体问题。
标签: c++ segmentation-fault ncurses