ローカル ネットワーク上の UDP パケットでブロードキャストされる神経スパイク データを処理するプログラムがあります。
私の現在のプログラムには、UI スレッドとワーカー スレッドの 2 つのスレッドがあります。ワーカー スレッドは単にデータ パケットをリッスンして解析し、UI スレッドで表示および処理できるようにします。私の現在の実装は問題なく動作します。しかし、さまざまな理由から、オブジェクト指向アプローチを使用して C++ でプログラムを書き直そうとしています。
現在の作業プログラムは、2 番目のスレッドを次のように初期化しました。
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 バージョンでは、ほぼ同じ方法で 2 番目のスレッドをセットアップします。
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++;
}
2 つの実装のコードはほぼ同じですが、2 番目の実装 (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 に設定するコンストラクターを除く)。これらの変数のその他の用途はすべて読み取り専用です。