读者 - 作家:分段错误c ++

时间:2016-04-09 17:06:48

标签: c++ writer consumer producer

所以我有一个模拟网络摄像头的小程序。所以帧(在我的程序中的数据值)必须保存在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;
}

有谁知道我的错在哪里,某处我认为有一个僵局,但我无法弄清楚在哪里。

1 个答案:

答案 0 :(得分:0)

我不知道你是否正在寻找它的错误,或者它是否是另一个错误,但......当你用这种方式写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;
}

你编写的函数可以返回NULL Data指针(当使用所有存储时)。

如果您在使用它之前测试返回的指针,但在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

潜在的崩溃。

与使用Buffer::getLastProducedData() lastProduced NULL的{​​{1}}相同的潜在问题?publish()通过Producer::run()来自Producer::produceData()的{​​{1}}收到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.txt

无论如何:如果您想要我们可以尝试您的计划,您应该给我们file2.txt<f:format.date format="d.m.Y - H:i:s">{event.appointment}</f:format.date>

P.s:抱歉我的英语不好