c++ - 在 C++ 和 Linux 中追踪总线错误/段故障时遇到问题

标签 c++ linux pthreads segmentation-fault bus-error

我有一个处理 neural spike data 的程序这是在本地网络上以 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作为类的私有(private)成员:

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 的构造函数之外)。这些变量的所有其他用途都是只读的。

最佳答案

我要在这里冒险说你所有的问题都是由spike_net_t数组的清零引起的。

在 C++ 中,您不得将具有非[在此处插入“类似结构”的单词]成员的对象归零。即,如果您有一个包含复杂对象(std 字符串、 vector 等)的对象,则无法将其清零,因为这会破坏构造函数中完成的对象的初始化。

关于c++ - 在 C++ 和 Linux 中追踪总线错误/段故障时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7603205/

相关文章:

c++ - 如何使用与错误报告无关的区域设置 strtod

c - 在 Qt-Creator SDK 上以 root 身份运行代码

linux - tcsh 脚本中设置的环境变量不适用于 bash 脚本

linux - fork 带线吗?

php - 在 Ubuntu 上的 PHP+Apache2 中启用线程安全 - 使用 pthreads 从源代码编译 php

c++ - 函数中的堆栈指针会是形参吗?

c++ - 读取 cin 时超出运行时间但从文件读取时未超出运行时间?

pthreads - 在MingW下编译简单的pthread代码时出现链接器错误

c++ - 在 C++ 程序中评估从 max 导出的 3d 样条曲线

c# - 创建进程 : error creating process handle