2017-02-23 2 views
1

주 프로그램의 모든 "파일 쓰기"작업을 수행하는 작은 프로그램을 작성하고 있습니다. 데이터는 일정한 크기가 아닌 Struct입니다. 그 중 많은 것들이 있으며 앞으로 새로운 것들이 추가 될 것입니다. 그 때문에 char 배열로 작업하고 메서드에서 메서드로 이러한 배열에 대한 포인터를 넘기로했습니다.파일에 문자 배열을 쓸 때 액세스 위반이 발생했습니다.

코드가 의도 한대로 실행되는 시간의 70 %이지만 어레이가 기록 될 때 종종 "액세스 위반"오류가 발생하며 때때로이 오류는 연속으로 세 번 발생합니다. 나는 패턴을 찾을 수 없다.

Execute는 다른 스레드에서 실행됩니다.

struct BufferElement 
{ 
    char* ptrData; 
    int TotalBytes; 
    int StartPosition; 
    std::string FileName; 
}; 

class FileThread 
{ 
private: 
    std::vector<BufferElement> Queue; 
    bool BoolThread; 
    std::ofstream writestream; 

//This Method calls the "WriteInFile" Method for the first element in the 
//Queue and erases it from the vector 
void Execute(void) 
{ 
    while(BoolThread) 
    { 
    if(Queue.size() > 0) 
    { 
     if(WriteInFile()) 
     { 
     delete[] Queue.at(0).ptrData; 
     Queue.erase(Queue.begin()); 
     } 
    } 
    } 
} 

//This Method writes the first Element of the Queue in the file 
bool WriteInFile(void) 
{ 
    if(Queue.at(0).ptrData == NULL) 
    { 
    return true; 
    } 

    writestream.open(Queue.at(0).FileName.c_str(), std::ios::in | 
         std::ios::out | std::ios::binary); 

    if(!writestream.is_open()) 
    { 
    writestream.close(); 
    writestream.clear(); 
    return false; 
    } 

    writestream.seekp(Queue.at(0).StartPosition); 
    writestream.write(Queue.at(0).ptrData, Queue.at(0).TotalBytes); 

    writestream.close(); 
    writestream.clear(); 

return true; 
} 

public: 
void EndThread(void) 
{ 
    BoolThread = false; 
    for(int i = 0; i < Queue.size(); i++) 
    { 
    delete[] Queue.at(i).ptrData; 
    } 
} 

template< typename T > 
void WriteOrder(std::string _FileName, T _Data, int _StartPosition) 
{ 
    BufferElement Temp_BufferElement; 
    Temp_BufferElement.TotalBytes = sizeof(_Data); 
    Temp_BufferElement.StartPosition = _StartPosition; 
    Temp_BufferElement.FileName = _FileName; 

    Temp_BufferElement.ptrData = new char[ Temp_BufferElement.TotalBytes ]; 
    memcpy(Temp_BufferElement.DataPtr, _Data, Temp_BufferElement.TotalBytes); 

    Queue.push_back(Temp_BufferElement); 
} 
}; 

int main(void) 
{ 
    std::string Path = "..\\Data\\Test.dat"; 
    FileThread Writer; 

    for(int i = 0; i < 1000; i++) 
    { 
    char array[] = {'H','e','l','l','o',' ','W','o','r','l','d','!','\0'}; 
    Writer.WriteOrder(Path, array, i * sizeof(array); 
    } 

    system("pause"); 
    Writer.EndThread(); 
    return 0; 
} 

누군가 코드를 살펴볼 수 있다면 기쁠 것입니다. 어쩌면 방금 뭔가를 간과 할 수 있습니다. Borland Turbo C++ Builder를 사용하고 있고 스레드는 vcl 클래스의 개체입니다.

+1

'EndThread'가'Execute'와는 다른 스레드에서 호출된다고 가정합니다. 그리고 나는 전혀 동기화를 보지 못합니다. – knivil

+0

예. 그것은 메인 스레드에서 호출됩니다. 동기화가 필요합니까? Execute 메서드 만 파일 – Schmelix

+0

에 액세스 할 수 있습니다. 스레드 작성 및 종료에 대한 전체 코드를 제공하지 않는 이유는 무엇입니까? – user

답변

2

대기열에 대한 액세스를 동기화해야합니다. 작업자 스레드가 큐를 수정하는 동안 주 스레드가 큐에 쓰면 충돌이 발생할 수 있습니다. 또한 push_back을 수행하면 작업자가 여전히 유효하지 않은 메모리로 작업하는 동안 배열 메모리가 유효하지 않을 수 있습니다.

BoolThread이 (가) 초기화되거나 변경된 곳이 표시되지 않습니다. 따라서이 예제는 불완전하거나 어쨌든 이상하게 작동 할 수 있습니다.

+0

벡터에 대한 잠금 장치가 추가되어 이제 100 번째 반복에서도 작동합니다. 감사합니다. – Schmelix

+0

'sizeof (Data)'문제를 확인해야합니다. 다른 부작용이 즉시 나타나지 않을 것입니다. – Devolus

0
void WriteOrder(std::string _FileName, T _Data, int _StartPosition) 
{ 
    BufferElement Temp_BufferElement; 
    Temp_BufferElement.TotalBytes = sizeof(_Data); 
    Temp_BufferElement.StartPosition = _StartPosition; 
    Temp_BufferElement.FileName = _FileName; 

    Temp_BufferElement.ptrData = new char[ Temp_BufferElement.TotalBytes ]; 
    memcpy(Temp_BufferElement.DataPtr, _Data, Temp_BufferElement.TotalBytes); 

    Queue.push_back(Temp_BufferElement); 
} 

이 같은 불리는 경우

Writer.WriteOrder(Path, array, i * sizeof(array)); 

Temp_BufferElement.TotalBytes가 개최 4 (8) (는 sizeof (_data)) 겉으로는 이것이 당신이 의도하지 않습니다. 이 줄은 :

Temp_BufferElement.ptrData = new char[ Temp_BufferElement.TotalBytes ]; 
     memcpy(Temp_BufferElement.DataPtr, _Data, Temp_BufferElement.TotalBytes); 

는 힙에 할당하고이 코드

(포인터의 크기, 32/64 비트 프로그램의 따라) 4 바이트를 복사합니다 :

Queue.push_back(Temp_BufferElement); 

이 코드 전에이 Queue.size() == Queue.capacity() 일 경우, 벡터는 "Execute"함수를 실행하는 스레드와 동기화 문제를 일으키는 자체를 재 할당합니다.