gpt4 book ai didi

c - 主循环不正常退出

转载 作者:行者123 更新时间:2023-11-30 17:48:42 24 4
gpt4 key购买 nike

我创建了这个函数,作为基于终端的应用程序的主菜单:

bool wizard_run() {
char *command = NULL;
bool repeat = false;
bookmark:

terminal_prepare();
terminal_message(MESSAGE_INTRODUCTION);

loop: /* repeat until a valid command */ {
free(command); /* free any previous command */
command = terminal_command(PROMPT_COMMAND, COMMAND_LENGTH, repeat);

if (!strcmp(command, COMMAND_ENCRYPT)) wizard_encrypt();
else if (!strcmp(command, COMMAND_DECRYPT)) wizard_decrypt();
else if (!strcmp(command, COMMAND_CONCEAL)) wizard_conceal();
else if (!strcmp(command, COMMAND_REVEAL)) wizard_reveal();
else if (!strcmp(command, COMMAND_ERASE)) wizard_erase();
else if (!strcmp(command, COMMAND_GENERATE)) wizard_generate();
else if (!strcmp(command, COMMAND_NAVIGATE)) directory_navigate(RDS_HOME)
else if (!strcmp(command, COMMAND_SESSION)) wizard_session();
else if (!strcmp(command, COMMAND_SAFEMODE)) wizard_safemode();
else if (!strcmp(command, COMMAND_HELP)) wizard_help(HELP_MAINMENU)
else if (!strcmp(command, COMMAND_EXIT)) {free(command); return false;}
else {repeat = true; goto loop;}
}

free(command); /* free last command */
return true;
}

所有大写值都是#define常量,所有...(...)都是函数,除了wizard_help(...)directory_navigate(...) 都是宏(这就是为什么没有分号结束这些行的原因)。

这是应用程序的主要功能:

void main() {
// initialize any Components needed
if (!directory_rdsload()) return;
packager_reset();

// show the Splash Screen
SPLASH();

// continuously execute the Main Thread
while (wizard_run()); /* execution loop */

// perform any Clean-UP needed before exit
reset();
encryption_reset();
directory_reset(is_safemode);
}

这里,只有 SPLASH() 是一个宏。

所有 bool 值(即truefalse)都是预定义的unsigned char值,而booltypedef unsigned char bool; .

它的正常行为是当用户输入 exit (COMMAND_EXIT 的当前值)时退出 wizard_run() 循环,执行 reset( );加密重置(); Directory_reset(is_safemode); 然后正常终止应用程序。相反,当我第一次输入 exit 时,它会重新显示菜单,当我第二次输入 exit 时,它会终止并显示以下错误:

application: cxa_atexit.c:99: __new_exitfn: Assertion `l != ((void *)0)' failed.
Aborted (core dumped)

当程序在gdb下运行时,我收到此错误:

application: cxa_atexit.c:99: __new_exitfn: Assertion `l != ((void *)0)' failed.

Program received signal SIGABRT, Aborted.
0xb7fdd424 in __kernel_vsyscall ()

除了 main() 之外,没有其他函数调用 wizard_run(),因此这不是菜单重新显示而不是退出的原因。有什么想法吗?

先谢谢了!!! :D

最佳答案

好吧,终于找到问题了!它位于 SPLASH() 内。这是一个宏,定义为:

#define SPLASH() { \
if (!vfork()) execlp("/bin/splash", "/bin/splash", NULL); \
else wait(); \
}

由于我的应用程序仍处于测试阶段,因此我没有将 splash 放在目录 /bin 中。我从没想过这会成为一个问题。但是,这里有一个问题:我使用 vfork 而不是 fork,因为我只想执行一个新程序(vfork 在以下情况下速度更快)您不需要子进程成为父进程的副本)。由于不存在 /bin/bash,因此 execlp 不会为子进程加载新的应用程序镜像。因此,我可以想象这两个进程正在共享其图像的一部分? (look here)

因此,当调用 SPLASH() 时,子进程将接管并再次显示主菜单。一切看起来都很好。但是当我调用 exit 时,子进程正常终止,父进程控制终端并重新显示主菜单(这就是它显示两次的原因!)。当再次调用exit时,就轮到父进程终止了。但是,子进程(一直与父进程共享相同的进程镜像)已经终止,从而更改了一些数据。一定是这个改变的数据导致了退出时的错误。

当我的函数清除终端并覆盖之前的消息时,我无法注意到子进程首先显示主菜单! ;)

我对整个问题的本质感到非常兴奋。虽然我无法更好地解释它(我的术语肯定犯了一些错误),但我希望你明白出了什么问题!感谢大家的有用评论(尤其是 WhozCraig)!!! :D

关于c - 主循环不正常退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18431686/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com