编辑:添加反引号到回调模板。界面正在读取星号作为降价指示器,而不仅仅是星号!
在我正在编写的Windows DLL / Linux中,我给用户app一种注册回调函数的方法。效果很好。回调原型看起来像(void)(*callback)(void*);
我在撰写文档时遇到了偏执,并意识到,我没有什么好办法知道注册地址是否有效。唯一的反馈是崩溃或在try / catch中调用回调。
如果回调不存在且谁知道执行了什么,我不知道会抛出什么异常。甚至不确定对“无处”的调用可以恢复到足以产生异常而不是崩溃。
是的,我知道这是用户的问题。只是想要深思熟虑,也许可以帮助用户理解他的错误。
那么,这会抛出什么异常?如果它们不同,Windows和Linux会回答。
或者,有没有更好的方法来解决这个问题而不必使用异常捕获来检测丢失的函数?
答案 0 :(得分:5)
没有办法恢复。同样,如果回调包含*(int*)(0x1234) = 5;
之类的行,则无法恢复。忍住吧。
作为一名C ++库开发人员,您不会确保任何事情都不会崩溃。您只需提供代码,以便按照文档的方式执行它所承诺的内容。
答案 1 :(得分:2)
有点偏离主题,但void(*)()
形式的回调,即取0参数,不太有用。有用的C风格回调接受用户指定的参数,以便用户可以找到与回调相对应的状态。 E.g:
typedef void callback_fn(void* user_arg);
callback_id register_callback(callback_fn* callback, void* user_arg);
void unregister_callback(callback_id);
如果没有user_arg
,您的回调用户将被强制使用全局变量来存储与回调函数相对应的状态。
答案 2 :(得分:1)
您描述的情况不太可能发生。我从来没有见过这样的处理。该程序将崩溃并毁掉其用户。
但是您的担忧是有效的,因为失败的根本原因(分配错误的地址)及其表现形式(调用无效地址)可能彼此相距甚远,以至于很难识别它。
我在这里所能提出的建议是“快速而大声地失败”#34;例如,您可以在分配回调时对其进行测试调用。这仍然会导致崩溃,但现在在堆栈跟踪中,用户将看到它从哪里开始。
同样,这不是普通图书馆用户所期望的......
答案 3 :(得分:0)
我在这里回答:
How to test if an instance is corrupted? (完全不同类型的问题,但同样适用)
如果指针“无法识别NULL或类似”,那么在代码中无法判断它是否有效。
您也无法使用try/catch
来捕获失败,因为“无法执行代码”不会导致抛出。
由于这是“程序员错误”,我不相信这是一个大问题。程序员无论如何都可以用他们自己的代码做他们喜欢的事情,所以无论你添加什么机制,它都有可能以某种方式规避。
答案 4 :(得分:0)
正如其他人所说,没有办法检查,但......是吗? 真的有必要?我全都赞成防守编程, 但唯一的方法是可以获得指向函数的指针 (除了空指针)是通过取地址 一个功能。一些编译器做允许显式转换 尽管如此,指向对象指向函数的指针 事实上,该标准要求在这种情况下进行诊断。但 即使这样,客户端代码也需要一个明确的强制转换。 与物体不同,功能在整个生命周期中都存在 该程序,所以你不能有悬挂的问题 指针 - 曾经有效的指针,但不是任何指针 更多。事实上,实际上没有办法获得无效 指向函数的指针,除了故意(唯一的方式) 发生在我身上的是如果用函数卸载DLL,如果 有人故意搞砸了,你没办法 能够阻止它。