curses程序开始运行时闪退、报错LINES value must be >= 2 and <= 29: got 30 initscr(): Unable to create SP解决办法

最近在写curses程序,但是发现在一台机器上可以运行的程序在另一台电脑上就打不开,同时也没有出现缺少dll的消息提示。正百思不得其解时发现在闪退的一瞬间控制台输出了几行字,于是在cmd上运行下,发现这行字是:

LINES value must be >= 2 and <= 29: got 30
initscr(): Unable to create SP

看到这个报错信息后解决办法就不辩自明了,报错的意思是行数太多无法调用initscr。所以只需要在intiscr前执行下面语句:

HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SMALL_RECT rc = {0, 0, 80, 20}; 
SetConsoleWindowInfo(hOut,true ,&rc);
//CloseHandle(hOut); // 这句要放在整个程序的末尾,或者不加

即更改控制台行数,这样就可以成功运行了。

需要注意的是,在程序结束前,不要把标准输出的句柄close掉,这样不论是c的运行库(如printf)还是initscr都无法执行。

不过看到这里肯定有人会想能否在initscr前获取一下该电脑的curses所支持的行数范围,笔者也想到这一点,不过由于自身才浅,并不能找到很好的方式在程序开始时获得这串错误码。

笔者想到通过CreateProcess调用自身,在子进程中先close掉标准输出的句柄,再调用initscr以触发报错,最后在父进程中通过获取子进程输出来获取错误码。可是笔者自身能力有限,无论是通过匿名管道读写还是重定向标准输出的方法,都无法在父进程中获得这串代码(父进程中获得的输出总为空)。甚至通过创建一个子进程,子进程用system打开输出错误码的程序,都无法获得错误码,无论是子进程还是父进程。

下面放出了我在尝试时用到的代码,读者可以在此基础上继续探索这个新问题的解决办法。如有高人精通此道,还请指点一二。

#define PDC_DLL_BUILD true
#pragma comment(lib,"pdcurses.lib")
#define _CRT_SECURE_NO_WARNINGS
#define DEBUG

#include <stdlib.h>
#include <string.h>
#include <Windows.h>
#include <iostream>
#include <ctime>
#include <string>
#include <conio.h>
#include "curses.h"

using std::string;

int SetSupportedLines()
{
	// 创建匿名管道
	SECURITY_ATTRIBUTES sa;
	HANDLE hRead, hWrite;

	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.lpSecurityDescriptor = NULL;
	sa.bInheritHandle = TRUE;

	if (!CreatePipe(&hRead, &hWrite, &sa, 0))
	{
		printf("Error On CreatePipe()");
		return -1;
	}
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	si.cb = sizeof(STARTUPINFO);
	GetStartupInfo(&si);

	si.hStdError = hWrite;
	si.hStdOutput = hWrite;
	si.wShowWindow = SW_HIDE;

	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;

	TCHAR cmd[256];
	strcpy_s(cmd, (string(_pgmptr) + " systemcall").c_str());

	BOOL bRet = ::CreateProcess(NULL, cmd, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);

	if (bRet == FALSE)
	{
		printf("Error on CreateProcess()");
		return -2;
	}

	CloseHandle(hWrite);

	char buffer[4096] = { 0 };
	DWORD bytesRead;
	printf("################################################################################\n");
	while (TRUE)
	{
		if (!ReadFile(hRead, buffer, 4095, &bytesRead, NULL))
			break;
		printf("%s\n", buffer);
	}
	CloseHandle(hRead);
	return 0;
}

int main(int argc, char **argv)
{
	if (argc > 1 )
	{
		if (strcmp(argv[1], "outputerr") == 0)
		{
			printf("outputerr proc\n"); DEBUG;

			CloseHandle(GetStdHandle(STD_OUTPUT_HANDLE));
			initscr();
			endwin();
			return 0;
		}
		if (strcmp(argv[1], "systemcall") == 0)
		{
			printf("systemcall proc\n"); DEBUG;

			TCHAR cmd[256];
			strcpy_s(cmd, (string(_pgmptr) + " outputerr").c_str());
			system(cmd);
			return 0;
		}
	}

	SetSupportedLines();

	getchar(); DEBUG;

	initscr();
	printw("curses startup successfully!");
	refresh();
	getch();
	endwin();
	return (0);
}

 如上图,只有systemcall的输出,而没有outputerr的输出,可见outputerr部分的输出并未被捕获。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值