读者-作者:分割错误c++

Readers - writer: Segmentation fault c++

本文关键字:错误 c++ 分割 作者 读者      更新时间:2023-10-16

所以我有一个模拟网络摄像头的小程序。因此,帧(在我的程序中是数据的值)必须保存在2个文件中并显示在屏幕上。但当我运行代码时,我会遇到分段错误;

#include <iostream>
#include <fstream>
#include <pthread.h>
#include <stdlib.h>
#include <windows.h>
#include <winbase.h>
#ifdef WIN32
#   include <process.h>
#else
#   include <time.h>
#endif
static void Error(const char *str)
{
    std::cerr << str << std::endl;
    exit(0);
}
class Data
{
public:
    Data() : refcount(0), value(0) {}
    void ref() { refcount++; }
    void unref() { refcount--;  }
    bool isUnused(){ return ( refcount == 0 ); }
    void setValue(int val){ value = val; }
    void print(std::ostream &ostr) { ostr << value << std::endl; }
private:
    unsigned int refcount;
    int value;
};
class Buffer
{
public:
    Buffer() : lastProduced(0) {}
public:
    Data *getEmptyDataElement()
    {
        Data *d = 0; /* = empty data element */;
        for (int i=0; i<BUFFERSIZE; i++)
        {
            if (storage[i].isUnused()) {
                d = &storage[i];
                break;
            }
        }
        return d;
    }
    Data *getLastProducedData(Data* previous)
    {
        // check if new element is available
        Data *d = lastProduced;
        d->ref();
        return d;
    }
    void publish(Data *d) /* update last produced, so getLastProducedData returns the correct element */
    {
        lastProduced = d;
    }
    void release(Data *d) /* update handled element, to make it available via getEmptyDataElement */
    {
        d->unref();
    }
private:
    static const int BUFFERSIZE = 10;
    Data storage[BUFFERSIZE];
    Data *lastProduced;
};
static void *start_thread(void *t);
class Thread
{
public:
    Thread() : tid(0) {}
    void start()
    {
        if( pthread_create(&tid, 0, start_thread, (void *) this) != 0 )
            Error("Error: failed to create thread");
    }
    void wait()
    {
        void *status;
        pthread_join(tid, &status);
    }
    static void sleep(unsigned int msecs)
    {
#ifdef WIN32
        if( SleepEx(msecs, TRUE) != 0 )
            Error("Error: SleepEx interrupted");
#else
        struct timespec timeout; // timeout value for wait function
        // prepare timeout value
        timeout.tv_sec = msecs / 1000;
        msecs -= timeout.tv_sec * 1000;
        timeout.tv_nsec = (1000 * msecs) * 1000;
        if( nanosleep(&timeout, 0) != 0 )
            Error("Error: nanosleep interrupted or failed");
#endif
    }
    virtual void run() = 0;
private:
    pthread_t tid;
};
static void *start_thread(void *t)
{
    reinterpret_cast<Thread *>(t)->run();
    return 0;
}
class Producer : public Thread
{
public:
    Producer(Buffer &b, long sequenceNumber) : buffer(b), sequenceNumber(sequenceNumber) {}
private:
    void run()
    {
        for(int i = 0; i < 1000; ++i)
        {
            Data *d = buffer.getEmptyDataElement();
            produceData(d);
            buffer.publish(d);
        }
    }
    void produceData(Data *d)
    {
        Thread::sleep((float(rand()) / RAND_MAX) * 1000); // sleep between 0 and 1 sec
        d->setValue(sequenceNumber++);
        d->print(std::cout);
    }
    Buffer &buffer;
    long sequenceNumber;
};

class Handler : public Thread
{
public:
    Handler(Buffer &b, std::ostream &ostr) : buffer(b), ostr(ostr) {}
private:
    void run()
    {
        Data *previous = 0;
        while( 1)
        {
            Data *d = buffer.getLastProducedData(previous);
            handleData(d);
            buffer.release(d);
            previous = d;
        }
    }
    void handleData(Data *d)
    {
        d->print(ostr);
        Thread::sleep((float(rand()) / RAND_MAX) * 1000); // sleep between 0 and 1 sec
    }
    Buffer &buffer;
    std::ostream &ostr;
};
int main()
{
    Buffer buff;
    std::ofstream file1;
    std::ofstream file2;
    file1.open ("file1.txt");
    file2.open ("file2.txt");
    // open the files
    Producer p(buff, 0);
    Handler h1(buff, std::cout), h2(buff, file1), h3(buff, file2);
    p.start();
    h1.start();
    h2.start();
    h3.start();
    p.wait();
    h1.wait();
    h2.wait();
    h3.wait();
    // wait until producers stopped producing and handlers handled all produced data
    return EXIT_SUCCESS;
}

有人知道我的错在哪里吗?我想在哪里出现了僵局,但我不知道在哪里。

我不知道这是你要找的故障还是另一个故障,但。。。当你用这种方式写你的Buffer::getEmptyDataElement()

Data *getEmptyDataElement()
{
    Data *d = 0; /* = empty data element */;
    for (int i=0; i<BUFFERSIZE; i++)
    {
        if (storage[i].isUnused()) {
            d = &storage[i];
            break;
        }
    }
    return d;
}

您编写了一个函数,该函数可以返回一个NULLData指针(当使用了所有存储器时)。

如果您测试之前返回的指针以使用它,这可能是很好的,但在Producer::run()

void run()
 {
     for(int i = 0; i < 1000; ++i)
     {
         Data *d = buffer.getEmptyDataElement();
         produceData(d);
         buffer.publish(d);
     }
 }

d指针传递给Producer::produceData()而不测试它和

void produceData(Data *d)
{
    Thread::sleep((float(rand()) / RAND_MAX) * 1000); // sleep between 0 and 1 sec
    d->setValue(sequenceNumber++); // what if 'd' is NULL?
    d->print(std::cout);           // what if 'd' is NULL?
}

Producer::produceData()使用它而不测试它是否是NULL

潜在的崩溃。

与使用lastProduced(如果Producer::produceData()测试值,则可以是publish()通过未测试值从Producer::run()接收的NULL?)而未测试其的Buffer::getLastProducedData()存在相同的潜在问题

Data *getLastProducedData(Data* previous)
{
    // check if new element is available
    Data *d = lastProduced;
    d->ref();  // what if 'lastProduced' (and so 'd') is NULL?
    return d;
}

不管怎样:如果你想让我们看你的节目,你应该给我们file1.txtfile2.txt

附言:很抱歉我的英语不好