【发布时间】:2016-03-05 16:24:15
【问题描述】:
解决方案显然,wgetstr 函数不会创建一个新缓冲区。如果第二个参数被称为data 并且大小为n 并且您输入的输入超过n 字符,它将访问并覆盖内存中不属于data 的部分,例如在存储cursorY 的内存。为了使一切正常,我用char data[] = " ";(八个空格)声明了data,并写了wgetnstr(inputWin, data, 8);。
----------------------------------------------- -------------------------------------------------- -------------
看来ncurses 函数wgetstr 确实在改变我的变量的值。在一个名为playGame 的函数中,我有一个名为cursorY(int 类型)的变量,每当我按下键盘上的向上或向下箭头时都会调整它(这工作正常)。
请看一下这段代码(inputWin 的类型是WINDOW*):
mvprintw(0, 0, (to_string(cursorY)).c_str());
refresh();
usleep(500000);
wgetstr(inputWin, data);
mvprintw(0, 0, (to_string(cursorY)).c_str());
refresh();
usleep(500000);
假设我将光标移动到第 6 行,然后按 Enter(这会导致这段代码被执行)。我可以做两件事:
- 只需输入 1 个字符。在两次
refresh调用之后,值 6 将显示在屏幕上(位置 (0, 0))。 - 输入 2 个或更多字符。在这种情况下,在第一次
refresh调用后,我只得到了 6,但在第二次之后,我神奇地得到了 0。
上面代码后面的前两行是
noecho();
_theView -> _theActualSheet -> putData(cursorY-1, cursorX/9 - 1, data);
(不要担心实际参数:关于它们的数学检查)。当我在putData 时,我得到一个Segmentation fault,而gdb 说putData 的第一个参数是-1,所以cursorY 必须是0(@987654346 的前两个参数@ 用于使用SheetCells[row][column] 访问二维数组,其中row 和column 分别是putData 的第一个和第二个形参。
很明显,wgetstr 修改了cursorY 的值。后一个变量的名称无关紧要:将其更改为 cursorrY 或类似 monkeyBusiness 的奇怪名称(是的,我已经尝试过了)不起作用。 某种的作用是将上面的代码替换为
mvprintw(0, 0, (to_string(cursorY)).c_str());
refresh();
usleep(500000);
int a = cursorY;
wgetstr(inputWin, data);
cursorY = a;
mvprintw(0, 0, (to_string(cursorY)).c_str());
refresh();
usleep(500000);
在这两种情况下,我都会在屏幕的左上角看到 6。但是,知道字符串的行为很奇怪:当我输入asdf 作为我的字符串,然后向右移动(即,我按键盘上的右键),然后再次输入asdf,我得到@ 987654358@.
所以基本上,我想知道两件事:
- 为什么
wgetstr会更改我的变量? - 为什么只有输入超过 1 个字符时才会出现这种情况?
- 一般来说
wgetstr似乎有什么问题?处理输入似乎很糟糕。
我可以尝试其他事情(例如手动读取字符,然后将 data 与它们连接),但 wgetstr 似乎非常适合我想做的事情,我没有理由切换到这里。
非常感谢任何帮助。 (请记住:我特别想知道为什么 cursorY 的值被更改。如果您建议不要使用 wgetstr 并有一个好的替代方案,请告诉我,但我最想知道为什么 @ 987654365@ 正在修改中。)
EDIT 变量data 的类型为char[],声明如下:char data[] = ""。我没有“清除”这个变量(即,删除所有“字母”),但我认为这没有任何区别,因为我认为 wgetstr 只是覆盖了整个变量(或者我在这里大错特错了吗?) .
【问题讨论】:
-
什么是
data,它是如何定义的?我敢打赌,你没有正确初始化它,导致cursorY被意外覆盖。 -
我已经编辑了我的问题,请看一下新的部分。
-
看起来@H.Guijt 有正确的想法。
wgetstr期望写入一个已分配且长度足以容纳输入字符串的缓冲区。您还没有使用data完成此操作,因此wgetstr正在写入缓冲区的末尾并写入接下来定义的任何变量。如果您的输入字符串足够长,我预计会发生更多损坏。 -
您宣称,几十年来没有问题使用的库有一个以前没有人注意到的严重错误。您自己的描述留下了足够的空间,这是您的错误。 向我们提供一个小测试用例来演示该错误,我们会看看是否可以帮助您解决问题。
-
@Dúthomhas wgetstr 函数可能已经有几十年的历史了,但我一眼就能看出一个主要的安全问题:它会让你通过无人看管的缓冲区。一旦引入 wgetnstr,它就应该被弃用。
标签: c++ string segmentation-fault ncurses