0

编辑:在回调模板中添加了反引号。界面将星号读取为降价指标,而不仅仅是星号!

在我正在编写的 Windows DLL/Linux SO 中,我为用户应用程序提供了一种注册回调函数的方法。效果很好。回调原型看起来像(void)(*callback)(void*);

我在编写文档时有点偏执,并意识到,我没有真正好的方法来知道注册地址是否有效。唯一的反馈是崩溃或在 try/catch 中调用回调。

我不知道如果回调不存在并且谁知道执行了什么会引发什么异常。甚至不确定对“无处”的调用是否可以恢复到足以生成异常而不是崩溃的程度。

是的,我知道这是用户的问题。只是想深思熟虑,也许可以帮助用户理解他的错误。

那么,这会抛出什么异常呢?如果 Windows 和 Linux 不同,请回答。

或者,有没有更好的方法来解决这个问题,而不必使用异常捕获来检测丢失的函数?

4

5 回答 5

6

没有办法恢复。同样,如果回调包含类似*(int*)(0x1234) = 5;. 忍受它。

作为 C++ 库开发人员,您的职责不是确保不会发生任何崩溃。您只需提供代码,当使用您记录的方式时,它会实现它所承诺的。

于 2013-04-10T13:03:53.327 回答
3

有点跑题了,但形式为 的回调void(*)(),即采用 0 个参数,用处不大。一个有用的 C 风格回调接受用户指定的参数,以便用户可以找到对应于回调的状态。例如:

typedef void callback_fn(void* user_arg);

callback_id register_callback(callback_fn* callback, void* user_arg);
void unregister_callback(callback_id);

没有user_arg你的回调的用户将被迫使用一个全局变量来存储对应于回调函数的状态。

于 2013-04-10T13:06:15.930 回答
2

你描述的情况不太可能。我从来没有在任何地方看到过这样的处理。该程序只会崩溃并毁掉它的用户。

但是您的担忧是有道理的,因为失败的根本原因(分配错误的地址)及其表现形式(调用无效地址)可能彼此相距甚远,以至于很难识别它。

我在这里只能建议“快速而响亮地失败”。例如,您可以在分配回调时对其进行测试调用。这仍然会导致崩溃,但现在在堆栈跟踪中,用户将看到这一切是从哪里开始的。

同样,这不是普通图书馆用户所期望的……

于 2013-04-10T13:08:01.777 回答
1

正如我在这里回答的:

如何测试实例是否损坏? (完全不同类型的问题,但同样适用)

如果指针是“不可识别的 NULL 或类似的”,那么在代码中就无法判断它是否有效。

您也不能使用try/catch捕获失败,因为“执行代码失败”不会导致抛出。

由于这是一个“程序员错误”,我不认为这是一个大问题。无论如何,程序员都可以用自己的代码做他们喜欢的事情,所以无论你添加什么机制,都可以以某种方式规避。

于 2013-04-10T13:05:26.050 回答
1

就像其他人所说的,没有办法检查,但是……真的有必要吗?我完全赞成防御性编程,但唯一可能获得指向函数的指针(空指针除外)的方法是获取函数的地址。一些编译器允许将指向对象的指针显式转换为指向函数的指针,尽管标准在这种情况下需要诊断。但即便如此,客户端代码也需要显式转换才能搞砸。与对象不同,函数在程序的整个生命周期中都存在,因此悬空指针不会有问题——一个曾经有效但不再有效的指针。实际上,除了故意之外,几乎没有办法获得指向函数的无效指针(我唯一想到的方法是使用函数卸载 DLL),如果有人故意想搞砸,那就没有办法了你将能够阻止它。

于 2013-04-10T13:26:33.797 回答