我使用共享内存和共享互斥锁编写了一些相对简单的通信协议。但后来我想扩大支持,以便在使用不同运行时的两个.dll之间进行通信。很明显,如果你有一些std::vector<__int64>
和两个dll - 一个vs2010,一个vs2015--他们不会相互礼貌地工作。然后我就想到了 - 为什么我不能在一侧以ipc方式结构序列化并在另一侧反序列化 - 然后vs run-times将相互平滑地工作。
长话短说 - 我已经创建了单独的接口,用于发送下一个数据块和请求下一个数据块。两者都在解码时工作 - 这意味着如果你有10个条目的向量,每个字符串1 Mb,共享内存是10 Kb - 那么传输整个数据需要1 * 10 * 1024/10次。每个下一个请求后跟多个未完成的函数调用 - 可以通过SendChunk或GetNextChunk取决于传输方向。
现在 - 我希望编码和解码同时发生但没有任何线程 - 然后我想出了使用setjmp和longjmp的解决方案。我附上下面的部分代码,只是为了让您了解整个机器中发生的事情。
#include "..."
#include <setjmp.h> //setjmp
class Jumper: public IMessageSerializer
{
public:
char lbuf[ sizeof(IpcCommand) + 10 ];
jmp_buf jbuf1;
jmp_buf jbuf2;
bool bChunkSupplied;
Jumper() :
bChunkSupplied(false)
{
memset( lbuf, 0 , sizeof(lbuf) );
}
virtual bool GetNextChunk( bool bSend, int offset )
{
if( !bChunkSupplied )
{
bChunkSupplied = true;
return true;
}
int r = setjmp(jbuf1);
((_JUMP_BUFFER *)&jbuf1)->Frame = 0;
if( r == 0 )
longjmp(jbuf2, 1);
bChunkSupplied = true;
return true;
}
virtual bool SendChunk( bool bLast )
{
bChunkSupplied = false;
int r = setjmp(jbuf2);
((_JUMP_BUFFER *)&jbuf2)->Frame = 0;
if( r == 0 )
longjmp(jbuf1, 1);
return true;
}
bool FlushReply( bool bLast )
{
return true;
}
IpcCommand* getCmd( void )
{
return (IpcCommand*) lbuf;
}
int bufSize( void )
{
return 10;
}
}; //class Jumper
Jumper jumper;
void main(void)
{
EncDecCtx enc(&jumper, true, true);
EncDecCtx dec(&jumper, false, false);
CString s;
if( setjmp(jumper.jbuf1) == 0 )
{
alloca(16*1024);
enc.encodeString(L"My testing my very very long string.");
enc.FlushBuffer(true);
} else {
dec.decodeString(s);
}
wprintf(L"%s\r\n", s.GetBuffer() );
}
这里有几个问题。在第一次调用setjmp后,我使用alloca() - 从堆栈中分配内存,它将在返回时自动同步。 alloca只能在第一次跳转时发生,因为任何函数调用总是使用callstack(以保存返回地址)并且它可以破坏第二个&#34; thread&#34;调用堆栈。
有很多文章讨论了setjmp和longjmp的危险程度,但现在这已经成为一种有效的解决方案了。堆栈大小(16 Kb)是下一个函数调用的预留 - decodeString等等 - 如果不够,它可以调整到更大。
尝试完这段代码后,我发现x86代码工作正常,但是64但是没有用 - 我遇到的问题与此处描述的类似:
An invalid or unaligned stack was encountered during an unwind operation
类似文章建议我添加了((_JUMP_BUFFER *)&jbuf1)->Frame = 0;
种重置 - 之后64位代码开始工作。目前库没有使用任何异常机制,我不打算使用任何机制(如果需要在编码*解码*函数调用中,将尝试捕获所有内容。
所以问题:
在代码中禁用展开是否可以接受? (((_JUMP_BUFFER *)&jbuf1)->Frame = 0;
)在上下文setjmp / longjmp中,unwinding的含义是什么?
您是否发现给定代码snipet存在任何潜在问题?