我正在尝试在C ++应用程序中实现通用消息传递系统。
该程序已被划分为不同的系统,它们处理诸如渲染,图像加载等不同的事情。我希望它们能够将消息推送到消息堆栈中,并带有某种类型的数据来进行传输。 / p>
为了实现这一点,我制作了一个允许这样做的API:
MessageStack.add(System * sender,
System * receiver,
MessageCodeEnum message_type,
void * data);
变量message_type
是一个枚举,它定义了所有消息命令,而void * data
应该是附加到消息的数据。这些消息按堆栈排列,并在每一帧的末尾进行评估。
假设renderer
消息fileLoader
加载图像。 renderer
将添加一条消息,告诉fileLoader
加载图像,并且该消息中将有一个void *
,实际上是一个指向包含以下内容的C字符串的const char *
图像文件的路径。
在处理该消息的函数中的switch case块中,我已经通过使用普通的旧方法将void *
的消息数据类型转换为const char *
了:
const char * temp = (const char *) data;
现在,这使我想到了这个问题。如果在任何消息事务期间,程序都知道要传输的是哪种数据,这就是为什么我有信心在类型广播void *
时使用void *
真的是不安全的方法吗?实现这样的功能?有没有更好的方法来达到这种宽松的类型检查水平?
答案 0 :(得分:6)
使用void
指针本质上是不安全的,因为对于程序员而言,滥用它们非常容易,并且编译器很少会诊断出滥用情况。程序员也往往对自己编写好的代码的能力过于自信,这在使用void
指针时效果不佳,因为它们很容易被滥用。
如果您犯了一个错误,并且错误地使用了指针(例如,将其强制转换为X *
,实际上它并不指向X
,然后访问X
的成员通过该指针),则代码的行为是不确定的。
更糟糕的是,程序员倾向于认为“我可以找到我在哪里犯了指针错误,因为程序会崩溃”。可悲的是:这常常是不正确的。大量的指针错误(尤其是void
指针的误用)贯穿于编译和测试而没有错误。要么是因为它们在测试中遗漏了(程序员不认为会发生这种情况,所以没有进行测试),要么是由于错误的结果不是崩溃(例如,使程序中的数据中毒,例如覆盖了无辜的变量) ,很少在发生时被检测到)。滥用void
指针会导致非常细微的滥用,以致在很长一段时间内都无法发现错误,这些症状会影响无关的代码,因此很难找到原因。
您可以通过精心的设计(以更难以滥用指针的方式进行设计),谨慎的编码(以最大程度地减少将设计转换为代码的错误)和彻底的测试(对代码进行全面的测试可以帮助您增强对代码不会滥用这些指针的信心。简而言之,这需要您付出时间和精力。但是,错过一件事,就会遇到麻烦。在设计过程中遗漏了某个特定的极端情况,您的程序将具有设计缺陷,从而导致指针滥用。引入一种错字,导致指针被滥用,这很麻烦。在测试过程中不要行使该设计缺陷,否则您将有个bug等待发现-在最坏的情况下,程序用户会发现它。
通常来说,最好使用一种不涉及使用void
指针的技术。指定数据和消息的接口,然后检查一下。以类型安全的方式提供数据。使用具有精心设计的一组操作的多态基类。选项列表继续。
如果您用尽了所有其他设计可能性,那么-是的-考虑使用void
指针。但是请接受它们是危险的,因此您将需要付出很多努力来确保您的消息传递系统稳定可靠,并最大程度地减少其他人(开发人员或最终用户)破坏它的机会。