2015-05-28 182 views
0

整整一天,我試圖找到解決方案,沒有任何結果。你是唯一的希望。我不得不做基於bass.h庫的聲音合成器。一切工作正常,直到我想它播放單獨的流。我決定做它在單獨的線程:C++線程 - 崩潰

void Synthezator::play(MonoStream *stream1, MonoStream *stream2) 
{ 
    threadParam data = {stream1, this}; 
    threadParam data2 = {stream2, this}; 
    int x = 6; 
    DWORD threadId; 
    DWORD threadId2; 
    //thread first (PlayThread, data); 
    //thread second (PlayThread, data2); 
    //first.join(); 
    //second.join(); 
    CreateThread(NULL, 0, PlayThread, (PVOID) &data, 0, &threadId); 
    CreateThread(NULL, 0, PlayThread, (PVOID) &data2, 0, &threadId2); 
    getchar(); 
} 

(以同樣的方式評價那些作品)

的崩潰隨機occures(隨機的時刻,不是每次)僅當兩個線程都在工作。如果我評論其中之一 - 沒有崩潰。

PlayThread功能:

DWORD WINAPI Synthezator::PlayThread(PVOID data) 
{ 
    //cout << "kurwa"; 
    int i=0; 
    threadParam* dataNew = (threadParam*) data; 
    dataNew->stream->SeekBegin(); 
    while(!(dataNew->stream->eof())) 
    { 
     int no = 0; 
     note* a = dataNew->stream->Next(&no); 
     dataNew->pointer->PlayNote(a, no); 
     i++; 
    } 
} 

PlayNote:

void Synthezator::PlayNote(note* note, int count) 
{ 
    position = new double[count]; 
    generatorParams params = {synthType, count, note, position, this}; 
    HSTREAM SignalStream = BASS_StreamCreate (FREQUENCY, 1, 0, &Generator, &params); 
    if (SignalStream == 0) throw " Cannot create stream"; 

    if(note->sound != 0) { 
     if (!BASS_ChannelPlay (SignalStream, TRUE)) throw "Cannot play generated sample"; 
    } 
    const int secinusecs = 1000000; 
     sleep(secinusecs*floor(note->duration)/1000000); 
     usleep(secinusecs*(note->duration-floor(note->duration))); 
    if(note->sound != 0) { 
     BASS_ChannelStop(SignalStream); 
    } 
    BASS_StreamFree(SignalStream); 
    delete [] position; 
} 

如果我評論這一行,沒有崩潰(也沒有聲音):

if (!BASS_ChannelPlay (SignalStream, TRUE)) throw "Cannot play generated sample"; 
+0

通過PlayThread中的第一個cout來判斷您一直在努力:D – AccessViolation

+0

聲明位置變量在哪裏?它從2個線程同時修改! – AccessViolation

+0

刪除行「delete [] position;」解決了這個問題。謝謝! – user1678401

回答

0

創建線程:

threadParam data = {stream1, this}; 
threadParam data2 = {stream2, this}; 
CreateThread(NULL, 0, PlayThread, (PVOID) &data, 0, &threadId); 
CreateThread(NULL, 0, PlayThread, (PVOID) &data2, 0, &threadId2); 

線程

dataNew->pointer->PlayNote(a, no); 

問題裏面是你使用的是相同的對象PlayNote功能可以從兩個不同的位置。因此,在線程1完成PlayNote之前,線程2進入PlayNote。 PlayNote中的第一件事是存儲在對象中的動態內存分配,所以線程2只是拋出了線程1的指針。線程1的行爲在哪一點變得不確定,並且一旦其他線程在第一個線程完成該函數並刪除該指針後切換回contex,就會發生崩潰。

歡迎使用多線程編程。這是你的帽子。

+0

我沒有編輯這些對象,所以我不明白爲什麼我不應該使用它們。無論如何,刪除行「刪除[]的位置;」解決了這個問題。 – user1678401

+0

當您修改位置時,您正在編輯PlayNote內的對象。通過刪除刪除,您已經引入了內存泄漏,並且在崩潰發生時會導致不確定的行爲。將位置設置爲PlayNote的本地位置,保留刪除是更好的解決方案。 – Aumnayan

0

如果position成員是唯一的成員,您在不同的線程修改那麼我建議你把後面的delete [] position;線和聲明爲私有變量位置:double* position = new double[count];

這樣每個線程都有自己的陣位。

雖然我必須看到整個代碼要確保其他成員不被多個線程修改。