2014-02-14 101 views
-1

我正在一個項目中工作,在這個項目中,我必須讀取一組文件並將其放入緩衝區。列表包含小文件和大文件。我必須讀取這些文件並更高的效率,我嘗試在多個線程中實現它。每個線程將從文件名向量中取出一個文件,並開始讀取它將其放入緩衝區,並且這些緩衝區必須放入隊列中。我碰巧在程序中出現了一些錯誤, ii不知道我的程序中究竟發生了什麼錯誤也不知道爲什麼?請幫助我判斷我的邏輯或代碼中是否有錯誤,以及如何糾正錯誤。在此先感謝將多個文件並行讀入一個緩衝區

using namespace std; 
#define MAX_THREADS 2 
#define BUFFER_SIZE 8388608 
vector<string>files; 
deque<string>bufferq; 
CRITICAL_SECTION Readlock; 
int count = 0; 

DWORD WINAPI ReadThread(LPVOID s); 
int main(int argc,char *argv[]) 
{ 
    HANDLE ReadT[MAX_THREADS]; 

    char *filelist[5]; 
    DWORD threadid; 
    filelist[0] = "1.txt"; 
    filelist[1] = "cloudy.jpg"; 
    filelist[2] = "connectify.exe"; 
    filelist[3] = "VMware.exe"; 
    filelist[4] = "Sherlock.mp4"; 
    for(int i=0;i<5;i++) 
     files.push_back(filelist[i]); 

    InitializeCriticalSection(&Readlock); 
    long t1 = GetTickCount(); 
    for(int k = 0; k< MAX_THREADS; k++) 
     ReadT[k] = CreateThread(NULL,0,ReadThread,NULL,NULL,&threadid); 

    WaitForMultipleObjects(MAX_THREADS,ReadT,TRUE,INFINITE); 
    cout << " Time Taken "<< GetTickCount()-t1 << "ms" ; 

    system("pause"); 
    return 0; 
} 
DWORD WINAPI ReadThread(LPVOID s) 
{ 
    long pending = 0; 
    //int freespace = BUFFER_SIZE; 
    char *filename = new char[50]; 
    char fsize[10]; 
    string file; 
    char *buf; 
    buf = new char[BUFFER_SIZE]; 
    long filesize = 0; 
    int numfiles = files.size(); 
    int filled = 0; 
    int i = 0; 
    FILE *fp; 
    char* ptr; 
    ptr = buf; 

    while(true) 
    { 
     EnterCriticalSection(&Readlock); 
     if(files.empty()) 
     { 
      LeaveCriticalSection(&Readlock); 
      break; 
     } 
     else 
     { 
      file = files.front(); 
      files.erase(files.begin()); 
      LeaveCriticalSection(&Readlock); 
     } 
     bool buff_full = false; 
     buf = ptr; 
     int freespace = BUFFER_SIZE; 
     memset(buf,0,BUFFER_SIZE); 
     if(!buff_full) 
     { 
      if(pending == 0) 
      { 
       fp = fopen(file.c_str(),"rb"); 
       if(!fp) 
        { 
         cout<<"\nNo such file"; 
         cout<<files[i]; 
         system("pause"); 
         return 0; 
        } 
       int r1 =fseek(fp, 0L, SEEK_END); 
       filesize = ftell(fp); 
       int r2 =fseek(fp, 0L, SEEK_SET); 
       sprintf(fsize, "%ld", filesize); 
       if(freespace >= (strlen(fsize) + strlen(file.c_str()) + 2)) 
       { 
        count++; 
        memcpy(buf, file.c_str(), strlen(file.c_str())+1); 
        freespace = freespace - strlen(file.c_str()) - 1; 
        buf += strlen(file.c_str()) + 1; 
        memcpy(buf,fsize,strlen(fsize)+1); 
        buf += strlen(fsize) + 1; 
        freespace = freespace - strlen(fsize) - 1; 
        cout<<"Files read is "<<count<<"\n"; 
        if(freespace == 0) 
        { 
         buff_full = true; 
         pending = filesize; 
         break; 
        } 
       } 
       else 
       { 
        filled = BUFFER_SIZE - freespace; 
        fclose(fp); 
        break; 
       } 
       if(freespace >= filesize) 
       { 
        fread(buf, 1, filesize, fp); 
        buf += filesize; 
        freespace = freespace - filesize; 
        bufferq.push_back(buf); 
        //cout << "pop"<<bufferq.size(); 
        //i++; 
        if(files.empty()) 
        { 
         filled = BUFFER_SIZE - freespace; 
         fclose(fp); 
         break; 
        } 
        fclose(fp); 
       } 
       else 
       { 
        fread(buf, 1, freespace, fp); 
        bufferq.push_back(buf); 
        //cout <<"pop "<<bufferq.size(); 
        buff_full = true; 
       } 
      } 
      else 
      { 
       if(freespace >= pending) 
       { 
        fread(buf, 1, pending, fp); 
        bufferq.push_back(buf); 
        freespace = freespace - pending; 
        pending = 0; 
        //i++; 
        if(files.empty()) 
        { 
         filled = BUFFER_SIZE - freespace; 
         fclose(fp); 
         break; 
        } 
        if(freespace > 0) 
         buf += pending; 
        else 
         buff_full = true; 
        fclose(fp); 
       } 
       else 
       { 
        fread(buf, 1, freespace, fp); 
        bufferq.push_back(buf); 
        cout << bufferq.size(); 
        pending = pending - freespace; 
        buff_full = true; 
       } 
      } 
     } 
     if(buff_full) 
     { 
      buf = ptr; 
      cout << "popping buffer " << bufferq.size(); 
      //bufferq.pop_back(); 
     } 
    } 
    return 0; 
} 
+0

首先你有沒有使用的變量(例如,你使用'filename'作什麼?)。其次,當你添加到'bufferq'時你有一個競爭條件。第三,是否有一個原因使用舊的C風格的'FILE'函數而不是C++流? –

+0

@JoachimPileborg我真的不知道什麼樣的競爭條件發生。對於適合緩衝區的文件來說,它是非常正常的。只有當我將一個文件添加到大小超過緩衝區的向量中時纔會出現錯誤。沒有理由使用C流。請你解釋一下嗎? – WarriorPrince

+0

對於競爭條件,如果多個線程同時嘗試向'bufferq'添加字符串會怎樣?至於緩衝區的問題,我建議你在一個調試器中運行並逐行通過代碼。至於我對未使用的變量的評論,你有更少的混亂和未使用的代碼,更容易更好地瞭解發生了什麼,這將有助於其他人在未來閱讀你自己的代碼*。 –

回答

0

在這種錯誤的大文件時出現的背景下,我想,這條線可能會導致問題

sprintf(fsize, "%ld", filesize); 

FSIZE是char [10],如果文件大小爲> = 1,000,000,000你將會以0結束覆蓋fsize數組。這將導致「運行時檢查失敗#2 - 圍繞變量'fsize'的堆棧被損壞。」,正如你寫的。請檢查您的測試文件的大小。

其中,你都盡顯環路文件上我,然後說:

files.erase(files.begin()); 
// ... 
cout<<"\nNo such file"; 
cout<<files[i]; 

文件[I]已經指向另外一個元素,你刪除他們,如果文件是空的最後迭代它會導致崩潰。

如果您不將它複製到bufferq,那麼您如何複製文件和fsize到buf?

由於bufferq是可寫的,並且在線程之間共享,所以對它的訪問應該按照您選擇的鎖定關鍵部分進行保護。

這是我的小代碼審查。

+0

@Alex ...現在感謝tats我真正需要的。複製文件和它的大小是爲了存儲元數據。你能告訴我如何改變我的循環,以便它能夠有效地讀取大小文件並將其插入隊列中? – WarriorPrince

+0

「複製文件及其大小用於存儲元數據」 - 很好,但不會將其複製到bufferq作爲bufferq.push_back(buf);不是從開頭拷貝緩衝區,而是從buf指針向前移動。這些元數據根本不被使用。 爲簡單起見,更改爲fsize [32] - 這應該修復堆棧幀的錯誤。 –

+0

@Alex ...非常感謝..但請告訴我如何通過多個線程將此讀取優化爲緩衝區以實現有效的並行性? – WarriorPrince

相關問題