我正在使用带有一些.C文件和.CPP文件的代码库。
系统中的多个线程调用C文件中的一些函数,如下所示。
void CalculateCrc(PWORD pwCRC, PBYTE pbyBuffer, DWORD dwBufferLen)
{
WORD wFCS = 0xffff;
ASSERT(pbyBuffer);
ASSERT(pwCRC);
while(dwBufferLen--)
{
wFCS = (WORD)(wFCS >> 8) ^ tbl_FCS[(wFCS ^ *pbyBuffer++) & 0xff];
}
wFCS ^= 0xffff; // complement
*pwCRC = wFCS;
}
对于每个调用线程,都会有参数[pwCRC,pbyBuffer,dwBufferLen]和函数[WORD wFCS]的非静态数据成员的副本,或者只有一组数据由所有线程共享数据损坏并使来自多个线程的调用不安全?
我不是以英语为母语的人。如果问题没有以明确的方式提出,请原谅我。
感谢您的时间。
答案 0 :(得分:3)
我相信每个线程都有自己的堆栈,这是产生过程的副本。 stack(我希望我在这个上技术上正确)。它们确实共享地址空间和堆。
所以在spawn之前存在的任何东西都会被共享。之后创建的任何东西都是线程本地的。因为所有内容都是按值传递的,而数据成员是非静态的,所以它将被创建为线程本地的。
您的功能本身是安全的。但是,由于您使用指针,因此需要注意两个线程不能在同一个内存区域上工作。变量是安全的,内存不是。
答案 1 :(得分:1)
会有参数副本[pwCRC,pbyBuffer,dwBufferLen]
在C中,参数按值传递,因此对于来自不同线程的每个调用,这些调用将被复制不同。但是,如果传递的变量是线程全局/共享的,那么所有这些线程都将传递相同的变量。
在你的情况下,PWORD pwCRC, PBYTE pbyBuffer
是指针。如果这些在线程之间共享,那么你的函数也不是线程安全的。因为多个线程可能会尝试更改这些指针指向的值。
函数的非静态数据成员[WORD wFCS]
是的,每个函数调用都会有副本。
答案 2 :(得分:1)
该函数将拥有自己的pwCRC和dwBufferLen副本但不是pbyBuffer,因为您将它作为指针传递。
我给出了两个解决方案:
一个。确保所有线程在调用此函数时只读取(或不读取)pbyBuffer;或(如果数据相当小
你可以通过复制来做到这一点。
B中。按值传递缓冲区。你可以通过使用结构
来做到这一点struct buffer { char buffer [LEN]; }
仅当缓冲区很小时才有效。如果我没记错的话,C ++标准将调用堆栈的大小限制为对VAX架构的让步。您的编译器可能超出标准的限制。即便如此,使用大量参数杀死堆栈也不是一个好主意。