Поиск и устранение неисправностей ошибки шины / ошибки сегмента в C ++ и Linux - PullRequest
2 голосов
/ 30 сентября 2011

У меня есть программа, которая обрабатывает данные нейронного пика , которые транслируются в пакетах UDP в локальной сети.

Моя текущая программа имеет два потока: поток пользовательского интерфейса и рабочий поток.Рабочий поток просто прослушивает пакеты данных, анализирует их и делает их доступными для потока пользовательского интерфейса для отображения и обработки.Моя текущая реализация работает просто отлично.Однако по разным причинам я пытаюсь переписать программу на 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-версии программы я настроил второй поток почти таким же образом:

void SpikePlot::initNetworkRxThread(){
    pthread_t netThread;
    net = NetCom::initUdpRx(host,port);
    pthread_create(&netThread, NULL, networkThreadFunc, this);
}

Однако, поскольку pthead_create принимает указатель на функцию void, а не указатель на метод-член объекта, мне нужно было создать эту простую функцию, которая обертывает

метод *1019*
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-я реализация (версия 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 Iвызовите:

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).Все остальные варианты использования этих переменных доступны только для чтения.

Ответы [ 4 ]

3 голосов
/ 30 сентября 2011

Я собираюсь остановиться здесь и сказать, что все ваши проблемы вызваны обнулением массива spike_net_t.

В C ++ вы не должны обнулять объекты с не- [вставить слово для слова "struct-like" здесь] членов. то есть, если у вас есть объект, который содержит сложный объект (стандартная строка, вектор и т. д.), вы не можете обнулить его, так как это разрушает инициализацию объекта, выполненную в конструкторе.

1 голос
/ 30 сентября 2011

Это может быть неправильно, но ....

Вы, кажется, переместили логику цикла ожидания из метода в статическую оболочку.Ничто не удерживает рабочий поток открытым, возможно, этот поток завершается после первого ожидания UDP-пакета, поэтому второй раз, статический метод sp теперь указывает на экземпляр, который вышел из области действия и был уничтожен?1004 * Можете ли вы попытаться утвердить (sp) в оболочке, прежде чем пытаться вызвать ее getNetworkSpikePacket ()?

0 голосов
/ 30 сентября 2011

Похоже, что ваш reinterpret_cast может вызывать некоторые проблемы. Когда вы вызываете pthread_create, вы передаете «this», которое является SpikePlot *, но внутри networkThreadFunc вы переводите его в TetrodePlot *.

Связаны ли SpikePlot и TetrodePlot? Это не вызвано тем, что вы опубликовали.

0 голосов
/ 30 сентября 2011

Если вы размещаете массив spikeBuff в любом месте, то убедитесь, что вы выделяете достаточно памяти, чтобы writeIdx не был за пределами индекса.

Я бы также проверил, что initNetworkRxThreadвызывается для выделенного экземпляра объекта spikePlot (а не только для объявленного указателя).

...