是否有某些版本的longjmp可以输出长值?

时间:2019-04-15 12:23:29

标签: c longjmp

我正在使用C语言开发框架,因为我想实现异常,因为我正在将longjump与setjump一起使用,但是在x64机器上,longjump仍会输出整数。

我创建了一个类(本质上是vptr的结构),它表示异常,但是要在代码中将其丢弃,我需要向该结构扔一个指针。对于x64机器,该指针具有 unsigned long long 值(qword),对于x86,该指针具有 unsigned int (dword),因此我只需要在输出中输入qword即可处理错误。

是否有longjmpsetjmp的实现可以输出qword?

或者我可以编写自己的longjump,但为此需要原始源代码。

2 个答案:

答案 0 :(得分:1)

如果要具有可移植性,则可以使用数组索引,到存储所有64位指针的数组(或者只是指向结构的指针数组,其中包含有关某些异常情况的信息页面)。 / p>

如何填充这样的数组是另一个问题。当然,您不需要用所有可能成为异常的实例填充数组,只需使用您已经 try -ed并且能够 catch 的实例。

但是,可能您不仅需要一个指针(因为您必须处理在堆栈中多个 active 处被捕获的具有相同异常的运行时情况)。

解决了上述问题后,一旦您了解了需要解决的问题的性质,甚至可以使用short int

基于阅读评论,我看到您评论说由于多线程问题,全局变量不适合。首先,您可以在线程上下文中将其 global (例如errno变量),因为这就是使用void *来调用例程的原因。线程执行,并在完成后返回。您可以在那里私密使用它来线程化全局数据。

第二点,如果您想从C的角度管理这些奇怪的事情,例如以怪异的方式操作堆栈,则上述功能是可以做到的(我不相信您完全知道{ {1}} / setjmp()的工作。)我可以告诉您longjmp() / setjmp() api是很久以前(现在已经有50年的历史了)在简单地说,使用longjmp()要复杂得多(强烈建议不要使用longjmp()),以解决不明的unix设备驱动程序错误处理(这是一个非常受控和简单的环境-)的时代。他们的作者K和R),而不是切换到完全支持其核心例外的另一种语言(如建议的C ++)(此建议不是我的,而是在您的问题的注释中建议了此建议)

第三。如果您使用setjmp()longjmp(),则还需要知道它们(都)使用调用线程的堆栈来标记指针和要去的地方来存储信息。因此,您必须进行控制,例如,如果您在信号处理程序中执行longjmp(),则可能严重破坏执行信号处理程序的线程的堆栈(这是被信号中断的线程)如果它与进行setjmp()调用的线程不同。这样做的原因是被中断的线程将使用执行setjmp()的线程之一来切换其堆栈,并且两个线程将在不同点开始使用同一堆栈执行代码,这跳回到了实现时两种功能(目前只有一台pdp计算机,没有今天常见的多个cpus /核,因此只有一个堆栈)您在这里必须特别小心,因为通常情况下,线程产生异常的地方与捕获的地方相同,但是对于异步陷阱(例如信号处理)来说,这可能是错误的。

顺便说一句,您正在做的事情非常有趣,它将使您知道语言如何实现内部复杂的行为,例如异常处理。我为您尝试这种事情的勇气鼓掌,不要犹豫,如果您需要C ++的指导者,我将为您服务。

别放弃!

答案 1 :(得分:1)

您可以将jmp_buf类型的变量括在更大的结构中,可能只包含sizeof(void*)。然后,在调用longjmp()之前,您可以将指针存储在该额外空间中。无需尝试将指针压缩为int。

示例:

#include <stdio.h>
#include <setjmp.h>

struct jmp_buf_struct
{
  jmp_buf jb;
  void* exc_ptr;
};

void may_throw(jmp_buf jb)
{
  struct jmp_buf_struct* jbs_ptr = (struct jmp_buf_struct*)jb;
  jbs_ptr->exc_ptr = "Exception message!";
  longjmp(jb, 1);
}

int main()
{
  struct jmp_buf_struct jbs;
  if (setjmp(jbs.jb))
  {
    printf("Threw %p = \"%s\".", jbs.exc_ptr, (char*)jbs.exc_ptr);
  }
  else
  {
    may_throw(jbs.jb);
    puts("Didn't throw.");
  }
  return 0;
}

Output

  

抛出0x55638ebc78c4 =“异常消息!”。