Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xcode和Curses.h打开终端时出错_Xcode_Macos_Gcc_Terminal_Curses - Fatal编程技术网

Xcode和Curses.h打开终端时出错

Xcode和Curses.h打开终端时出错,xcode,macos,gcc,terminal,curses,Xcode,Macos,Gcc,Terminal,Curses,我正在尝试用Xcode编译一个简单的诅咒项目。 该程序在带有-lcurses标志的终端中使用g++进行良好编译,并且运行良好。 创建了一个C++类型的命令行工具。 将curses.h导入我的main。 在目标“程序”信息->常规->链接库中,添加了libCurses.dylib 它可以正常编译,但终端窗口不会打开。 在调试控制台中,输出为, 已加载程序。 运行 [切换到流程3424] 打开终端时出错:未知。 正在运行… 我可以进入build文件夹,在terminal中打开程序,但是xcode有没

我正在尝试用Xcode编译一个简单的诅咒项目。
该程序在带有-lcurses标志的终端中使用g++进行良好编译,并且运行良好。

创建了一个C++类型的命令行工具。 将curses.h导入我的main。
在目标“程序”信息->常规->链接库中,添加了libCurses.dylib

它可以正常编译,但终端窗口不会打开。
在调试控制台中,输出为,

已加载程序。
运行
[切换到流程3424]
打开终端时出错:未知。
正在运行…

我可以进入build文件夹,在terminal中打开程序,但是xcode有没有办法打开终端

谢谢你的帮助!

Xcode IDE中没有要连接的终端。 而是从shell运行程序(通过终端应用程序)

如果您想使用IDE调试器(只是gdb),您可以附加 这是一个过程。首先获取进程id

gdb> attach mypid
为了获得更方便的方法,我将引用Xcode:MacOSX开发的步骤

在中打开可执行文件组 组和文件列表,选择应用程序,打开信息窗口,然后 在“调试”选项卡中,取消选中“开始” 启动调试器后可执行。 准备调试时,启动 调试器,然后启动 智能交通系统中的目标应用 环境在调试器的gdb中 控制台,键入attach myprogram,和 您的调试任务正在进行中


我在Xcode中调试ncurses时也遇到同样的问题。最后,我找到了一种使用Terminal.app管理调试的好方法,它允许调试ncurses

正如我们所知,要初始化和使用ncurses,我们需要在终端上运行我们的应用程序。但当我们按下运行按钮时,Xcode并没有打开终端。所以,如果我们从代码中请求环境变量
TERM
,我们将得到
NULL
。这就是应用程序在
initscr()上崩溃的原因

因此,需要启动Terminal.app,在那里执行我们的流程,并将调试器附加到它。可以通过方案设置来实现。我是在Xcode 11.4中完成的。我基于
语言:
C++
创建了一个新的macOS命令行工具项目。我还在
框架和库中添加了
libncurses.tbd
依赖项

转到
Product>Scheme>Edit Scheme…
,选择
Run
Scheme和
Run
action并导航到
Info
选项卡。您将看到
Launch
自动设置为
。将其更改为
等待启动可执行文件

运行
方案中选择
预操作
,然后添加
新运行脚本操作
。将
提供构建设置从
无更改为构建目标。在此处添加以下代码:

osascript -e 'tell application "Terminal"' -e 'delay 0.5' -e 'activate' -e "do script (\"$TARGET_BUILD_DIR/$PRODUCT_NAME\")" -e 'end tell' &

要在调试会话结束时选择性地关闭终端,请在
Run
方案中选择
Post actions
,然后添加
New Run Script Action
。添加以下代码:

osascript -e 'activate application "Terminal"' -e 'delay 0.5' -e 'tell application "System Events"' -e 'tell process "Terminal"' -e 'keystroke "w" using {command down}' -e 'end tell' -e 'end tell'
实际上,osascript将始终创建至少两个终端窗口,但如果您将第一个窗口保持打开状态,它将通过Pre和Post操作自动创建并销毁会话中的第二个窗口

您可能还会遇到调试器附加问题。我不知道为什么Xcode不想在进程外部执行时附加调试器,但我发现了这个问题。在调试会话开始时,我还发现
stdin
流处于奇怪的状态。因此,我基于
pselect
call编写了一个变通方法。我要求
stdin
获取任何数据,直到它没有返回成功。我发现在这些操作之后,调试器会感觉正常,
stdin
请求也会正常。下面是我的代码示例:

#include <stdlib.h>
#include <string.h>
#include <ncurses.h>
#include <sys/select.h>
#include <unistd.h>
#include <errno.h>

bool g_has_terminal = false; // Check this global variable before ncurses calls

bool ensure_debugger_attached_woraround(int timeout_ms)
{
    fd_set fd_stdin;
    FD_ZERO(&fd_stdin);
    FD_SET(STDIN_FILENO, &fd_stdin);
    struct timespec timeout = { timeout_ms / 1000, (timeout_ms % 1000) * 1000000 };

    do
    {
        errno = 0;
    }
    while (pselect(STDIN_FILENO + 1, &fd_stdin, NULL, NULL, &timeout, NULL) < 0 && errno == EINTR);

    if (errno != 0)
    {
        fprintf(stderr, "Unexpected error %d", errno);
        return false;
    }

    return true;
}

int main(int argc, const char *argv[])
{
    if (!ensure_debugger_attached_woraround(700))
        return 1;

    char *term = getenv("TERM");

    g_has_terminal = (term != NULL);

    if (g_has_terminal)
        g_has_terminal = (initscr() != NULL);

    // Some ncurses code. Maybe you should terminate if g_has_terminal is not set

    if (g_has_terminal)
    {
        printw("Press any key to exit...");
        refresh();

        getch();

        endwin();
    }

    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
bool g_has_terminal=false;//在调用ncurses之前检查此全局变量
bool确保\u调试器\u已连接\u工作区(int超时\u毫秒)
{
fd_设置fd_标准;
FD_ZERO(和FD_stdin);
FD_集(标准文件号和标准文件号);
结构timespec timeout={timeout\u ms/1000,(timeout\u ms%1000)*1000000};
做
{
errno=0;
}
而(pselect(STDIN\u FILENO+1,&fd\u STDIN,NULL,NULL,&timeout,NULL)<0&&errno==EINTR);
如果(错误号!=0)
{
fprintf(标准,“意外错误%d”,错误号);
返回false;
}
返回true;
}
int main(int argc,const char*argv[]
{
如果(!确保安装了调试器(700))
返回1;
char*term=getenv(“术语”);
g_有_终端=(term!=NULL);
如果(g_有_终端)
g_具有_端子=(initscr()!=NULL);
//一些ncurses代码。如果g_has_终端未设置,可能应该终止
如果(g_有_终端)
{
printw(“按任意键退出…”);
刷新();
getch();
endwin();
}
返回0;
}

确保调用\u debugger\u attached\u worround
时超时700毫秒。我尝试了不同的值,发现500毫秒是不可跳过的最小值
pselect
。也许这个超时是由机器决定的,我不知道。您可以通过
#ifdef#endif
或其他一些检查,可能通过特殊的命令行参数检查,以排除释放模式中的一些等待开销。

在XCode 8中,您可以选择在终端内运行,从编辑方案。。。选项页。

尽管在我的快速测试中,它似乎并不那么有效;它有时(并非总是)似乎“丢失”调试对象,或者调试对象从未启动,并认为它仍在运行。如果您试图退出,Xcode就会被卡住。我发现,如果找到并杀死一个名为
lldb rpc server
的进程,就可以避免强制退出

更详细地说(如果这对任何人都有帮助),只要调试对象无法启动
#include <stdlib.h>
#include <string.h>
#include <ncurses.h>
#include <sys/select.h>
#include <unistd.h>
#include <errno.h>

bool g_has_terminal = false; // Check this global variable before ncurses calls

bool ensure_debugger_attached_woraround(int timeout_ms)
{
    fd_set fd_stdin;
    FD_ZERO(&fd_stdin);
    FD_SET(STDIN_FILENO, &fd_stdin);
    struct timespec timeout = { timeout_ms / 1000, (timeout_ms % 1000) * 1000000 };

    do
    {
        errno = 0;
    }
    while (pselect(STDIN_FILENO + 1, &fd_stdin, NULL, NULL, &timeout, NULL) < 0 && errno == EINTR);

    if (errno != 0)
    {
        fprintf(stderr, "Unexpected error %d", errno);
        return false;
    }

    return true;
}

int main(int argc, const char *argv[])
{
    if (!ensure_debugger_attached_woraround(700))
        return 1;

    char *term = getenv("TERM");

    g_has_terminal = (term != NULL);

    if (g_has_terminal)
        g_has_terminal = (initscr() != NULL);

    // Some ncurses code. Maybe you should terminate if g_has_terminal is not set

    if (g_has_terminal)
    {
        printw("Press any key to exit...");
        refresh();

        getch();

        endwin();
    }

    return 0;
}
ps x | grep lldb
kill 12345