在c++和Linux中查找总线错误/Seg故障的问题
Trouble tracking down a Bus Error/Seg Fault in C++ and Linux
我有一个程序,处理在本地网络上以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:%dn", 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:%dnn", 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的构造函数),这些变量的所有其他用途都是只读的。
我将在这里冒昧地说,您的所有问题都是由spike_net_t数组的归零引起的。
在c++中,不能将非[此处插入'类结构'的词]成员归零。例如,如果你有一个对象包含一个复杂对象(STD字符串,矢量等),你不能将其归零,因为这会破坏构造函数中完成的对象初始化。
这可能是错误的但是....
您似乎将等待循环逻辑从方法中移到了静态包装器中。由于没有任何东西保持工作线程打开,也许该线程在您第一次等待UDP数据包后终止,所以第二次,静态方法中的sp现在指向一个已经离开作用域并被销毁的实例?
在尝试调用其getNetworkSpikePacket()之前,您可以尝试在包装器中断言(sp)吗?
看起来您的reinterpret_cast可能会引起一些问题。当你调用pthread_create时,你正在传递"this",这是一个SpikePlot*,但在networkThreadFunc中,你正在将它转换为一个tetrodeploy *。
SpikePlot和tetrodeploy相关吗?
如果你在任何地方分配spikeBuff
数组,那么确保你分配了足够的存储空间,所以writeIdx
不是一个越界索引。
我还检查initNetworkRxThread
是否在spikePlot
对象的分配实例上被调用(而不仅仅是在声明的指针上)。
- C++函数过载会导致 SEG 故障
- 带升压的 SEG 故障::make_shared / 特征3 内存.h.
- C ;使用lambdas在类中有条件地扩展功能(MWE的SEG故障)
- lambda回调中Android Cocos2D-X应用程序上的SEG故障
- 访问索引指向向量元素时的seg故障 - 做错了什么
- 如何修复strlen seg故障
- 将内存分配给指针数组时SEG故障
- MPI Hello World上的Valgrind SEG故障
- 迭代器越来越多,并导致SEG故障
- 复制CORBA ::任何包含字符串的corba程序SEG故障
- 当有1个以上的对象时,动态字符串类断裂与SEG故障
- C AVX2:访问数组数组中的地址时SEG故障
- SEG故障取决于指针分配的顺序
- 为什么C 线引起SEG故障
- std::map 的比较器函数中的 SEG 故障/未定义行为
- C/C++ 字符串错误与 ARM SEG 故障总线错误
- Taglib设置专辑图片,但给出了SEG故障
- 低内存会导致本机代码中的SEG故障
- STD上的SEG故障::设置整数插入
- SEG故障仅发生每次跑步