我有一个程序可以处理在本地网络上以 UDP 数据包广播的神经尖峰数据。
我当前的程序有两个线程,一个 UI 线程和一个工作线程。工作线程只是侦听数据包,解析它们并使它们可用于 UI 线程以进行显示和处理。我目前的实现工作得很好。但是由于多种原因,我试图使用面向对象的方法在 C++ 中重新编写程序。
当前工作程序使用以下命令初始化第二个线程:
pthread_t netThread;
net = NetCom::initUdpRx(host,port);
pthread_create(&netThread, NULL, getNetSpike, (void *)NULL);
这是getNetSpike
新线程调用的函数:
void *getNetSpike(void *ptr){
while(true)
{
spike_net_t s;
NetCom::rxSpike(net, &s);
spikeBuff[writeIdx] = s;
writeIdx = incrementIdx(writeIdx);
nSpikes+=1;
totalSpikesRead++;
}
}
现在,在我新的 OO 版本的程序中,我以几乎相同的方式设置了第二个线程:
void SpikePlot::initNetworkRxThread(){
pthread_t netThread;
net = NetCom::initUdpRx(host,port);
pthread_create(&netThread, NULL, networkThreadFunc, this);
}
但是,因为pthead_create
需要一个指向 void 函数的指针而不是指向对象成员方法的指针,所以我需要创建这个简单的函数来包装该SpikePlot.getNetworSpikePacket()
方法
void *networkThreadFunc(void *ptr){
SpikePlot *sp = reinterpret_cast<SpikePlot *>(ptr);
while(true)
{
sp->getNetworkSpikePacket();
}
}
然后调用该getNetworkSpikePacket()
方法:
void SpikePlot::getNetworkSpikePacket(){
spike_net_t s;
NetCom::rxSpike(net, &s);
spikeBuff[writeIdx] = s; // <--- SegFault/BusError occurs on this line
writeIdx = incrementIdx(writeIdx);
nSpikes+=1;
totalSpikesRead++;
}
两个实现的代码几乎相同,但第二个实现(OO 版本)在读取第一个数据包后因 SegFault 或 BusError 而崩溃。使用printf
我已经缩小了导致错误的行:
spikeBuff[writeIdx] = s;
对于我的一生,我无法弄清楚为什么它会导致我的程序崩溃。
我在这里做错了什么?
更新:我定义spikeBuff
为类的私有成员:
class SpikePlot{
private:
static int const MAX_SPIKE_BUFF_SIZE = 50;
spike_net_t spikeBuff[MAX_SPIKE_BUFF_SIZE];
....
}
然后在 SpikePlot 构造函数中我调用:
bzero(&spikeBuff, sizeof(spikeBuff));
并设置:
writeIdx =0;
更新 2:好的,我的索引变量发生了一些非常奇怪的事情。为了测试他们的理智,我改为getNetworkSpikePacket
:
void TetrodePlot::getNetworkSpikePacket(){
printf("Before:writeIdx:%d nspikes:%d totSpike:%d\n", writeIdx, nSpikes, totalSpikesRead);
spike_net_t s;
NetCom::rxSpike(net, &s);
// spikeBuff[writeIdx] = s;
writeIdx++;// = incrementIdx(writeIdx);
// if (writeIdx>=MAX_SPIKE_BUFF_SIZE)
// writeIdx = 0;
nSpikes += 1;
totalSpikesRead += 1;
printf("After:writeIdx:%d nspikes:%d totSpike:%d\n\n", writeIdx, nSpikes, totalSpikesRead);
}
我得到以下输出到控制台:
Before:writeIdx:0 nspikes:0 totSpike:0
After:writeIdx:1 nspikes:32763 totSpike:2053729378
Before:writeIdx:1 nspikes:32763 totSpike:2053729378
After:writeIdx:1 nspikes:0 totSpike:1
Before:writeIdx:1 nspikes:0 totSpike:1
After:writeIdx:32768 nspikes:32768 totSpike:260289889
Before:writeIdx:32768 nspikes:32768 totSpike:260289889
After:writeIdx:32768 nspikes:32768 totSpike:260289890
此方法是我更新它们的值的唯一方法(除了我将它们设置为 0 的构造函数)。这些变量的所有其他用途都是只读的。