2014-09-21 12 views
4

첫째 :다중 스레드 거품입니다. 델파이 7에서는 잘 작동하지만 나사로와는 잘 작동하지 않습니까? 컴파일러 버그? 난 당신이 내 코드를 보여 드리고자합니다 모든

unit BSort; 

{==============================================================================} 

{$mode objfpc}{$H+} 

{==============================================================================} 

interface 

{==============================================================================} 

uses 
    Classes, SysUtils; 

{==============================================================================} 

type 
    TcompFunc = function(AValue1, AValue2 : Integer) : boolean; 
    TIntegerArray = array of integer; 
    PIntegerArray = ^TIntegerArray; 

{==============================================================================} 

procedure BubbleSort(var AMatrix : TIntegerArray; ACompFunc : TCompFunc); 
function V1LargerV2(AValue1, AValue2 : Integer) : Boolean; 

{==============================================================================} 

implementation 

{==============================================================================} 

procedure Swap(var AValue1, AValue2 : Integer); 
var 
    Tmp : Integer; 
begin 
    Tmp := AValue1; 
    AValue1 := AValue2; 
    AValue2 := Tmp; 
end; 

{==============================================================================} 

function V1LargerV2(AValue1, AValue2 : Integer) : Boolean; 
begin 
    result := AValue1 > AValue2; 
end; 

{------------------------------------------------------------------------------} 

procedure BubbleSort(var AMatrix : TIntegerArray; ACompFunc : TCompFunc); 
var 
    i,j : Word; 
begin 
    for i := Low(AMatrix) to High(AMatrix) - 1 do 
    for j := Low(AMatrix) to High(AMatrix) - 1 do 
    begin 
     if ACompFunc(AMatrix[j], AMatrix[j+1]) then 
     Swap(AMatrix[j], AMatrix[j+1]); 
    end; 
end; 

{==============================================================================} 

end. 

unit MultiThreadSort; 

{==============================================================================} 

{$mode objfpc}{$H+} 

{==============================================================================} 

interface 

{==============================================================================} 

uses 
    Classes, SysUtils, BSort; 

{==============================================================================} 

type 
    TSortThread = class(TThread) 
     FMatrix : PIntegerArray; 
    protected 
     procedure Execute; override; 
    public 
     constructor Create(var AMatrix : TIntegerArray); 
    public 
     property Terminated; 
    end; 

{==============================================================================} 

implementation 

{==============================================================================} 

constructor TSortThread.Create(var AMatrix : TIntegerArray); 
begin 
    inherited Create(False); 
    FreeOnTerminate := False; 
    FMatrix := @AMatrix; 
end; 

{------------------------------------------------------------------------------} 

procedure TSortThread.Execute; 
begin 
    BubbleSort(FMatrix^, @V1LargerV2); 
end; 

{==============================================================================} 

end. 


program sortuj; 

{==============================================================================} 

{$mode objfpc}{$H+} 

{==============================================================================} 

uses 
    {$IFDEF UNIX}{$IFDEF UseCThreads} 
    cthreads, 
    {$ENDIF}{$ENDIF} 
    Classes, SysUtils, MultiThreadSort, BSort, Crt; 

{==============================================================================} 

const 
    Zakres = 20; 

{==============================================================================} 

var 
    Start : Double; 
    Stop : Double; 
    Time : array[0..1] of Double; 
    Matrix : array[0..9] of TIntegerArray; 
    i,j : Word; 

{==============================================================================} 

procedure Sort(var AMatrix : TIntegerArray); 
var 
    SortThread : array[0..1] of TSortThread; 
    Matrix  : array[0..1] of TIntegerArray; 
    Highest : Integer; 
    i, j, k : Word; 
begin 
    // Znalezienie największej liczby w tablicy. 
    Highest := Low(Integer); 
    for i := Low(AMatrix) to High(AMatrix) do 
    if AMatrix[i] > Highest then 
     Highest := AMatrix[i]; 

    // Zerowanie tablic pomocniczych. 
    for i := 0 to 1 do 
    SetLength(Matrix[i], 0); 

    // Podział tablicy do sortowania na dwie tablice: 
    // - pierwsza od najniższej do połowy najwyższej liczby. 
    // - druga od połowy najwyższej do najwyższej liczby. 
    j := 0; 
    k := 0; 
    for i := Low(AMatrix) to High(AMatrix) do 
    if AMatrix[i] < Highest div 2 then 
    begin 
     SetLength(Matrix[0], Length(Matrix[0]) + 1); 
     Matrix[0,j] := AMatrix[i]; 
     Inc(j); 
    end 
    else 
    begin 
     SetLength(Matrix[1], Length(Matrix[1]) + 1); 
     Matrix[1,k] := AMatrix[i]; 
     Inc(k); 
    end; 

    //Tworzenie i start wątków sortujacych. 
    for i := 0 to 1 do 
    SortThread[i] := TSortThread.Create(Matrix[i]); 

    // Oczekiwanie na zakończenie watków sortujących. 
    //for i := 0 to 1 do 
    // SortThread[i].WaitFor; 
    // while not SortThread[i].Terminated do 
    // sleep(2); 

    Sleep(10); 
    SortThread[0].WaitFor; 
    Sleep(10); 
    SortThread[1].WaitFor; 
    Sleep(10); 

    // Zwalnianie wątków sortujacych. 
    for i := 0 to 1 do 
    FreeAndNil(SortThread[i]); 

    // Łączenie tablic pomocniczych w jedną. 
    k := 0; 
    for i := 0 to 1 do 
    for j := Low(Matrix[i]) to High(Matrix[i]) do 
    begin 
     AMatrix[k] := Matrix[i,j]; 
     Inc(k); 
    end; 
end; 

{==============================================================================} 

begin 
    Randomize; 
    ClrScr; 

    for i := 0 to 9 do 
    begin 
    SetLength(Matrix[i],Zakres); 
    Write('Losowanie ', i, ' tablicy...'); 
    for j := 0 to Zakres - 1 do 
     Matrix[i,j] := Random(100) - 50; 
    Writeln('Wylosowana'); 
    end; 

    Writeln; 
    Start := TimeStampToMsecs(DateTimeToTimeStamp(Now)); 
    for i := 0 to 9 do 
    begin 
    Write('Sortowanie ', i, ' tablicy...'); 
    BubbleSort(Matrix[i],@V1LargerV2); 
    Writeln('Posortowana'); 
    end; 
    Stop := TimeStampToMsecs(DateTimeToTimeStamp(Now)); 
    Time[0] := Stop - Start; 

    Writeln; 
    for i := 0 to 9 do 
    begin 
    Write('Losowanie ',i,' tablicy...'); 
    for j := 0 to Zakres do 
     Matrix[i,j] := Random(100) - 50; 
    Writeln('Wylosowana'); 
    end; 

    Writeln; 
    Start := TimeStampToMsecs(DateTimeToTimeStamp(Now)); 
    for i := 0 to 9 do 
    begin 
    Write('Sortowanie dwuwatkowe ', i, ' tablicy...'); 
    Sort(Matrix[i]); 
    Writeln('Posortowana'); 
    end; 
    Stop := TimeStampToMsecs(DateTimeToTimeStamp(Now)); 
    Time[1] := Stop - Start; 

    Writeln; 
    Writeln('Sortowanie bąbelkowe : ',Time[0]); 
    Writeln('Sortowanie dwuwatkowe: ',Time[1]); 
    Readln; 
end. 

것은 그 코드를 컴파일하고 벌금을하고있다 델파이 7을 실행하는 경우. 그러나 나사로와 함께 그것을 컴파일 할 때, 마지막 "writeln"텍스트는 두 배가되거나 세 배가되고 프로그램은 중단됩니다. 누군가 왜 저에게 말할 수 있습니까?

델파이 7 올바른 : Delphi 7

나사로가 올바르지 않습니다 : Lazarus

+0

관찰 한 내용을 표시하고 예상되는 결과물을 설명해 주실 수 있습니까? 또한 왜 당신이'PIntegerArray'를 선언하는지 궁금합니다. 이를 제거하고 이미 참조 인 'TIntegerArray'를 사용하십시오. –

+0

편집과 관련하여 이미지를 업로드 할 필요가 없습니다. 이 모든것이 콘솔 앱일 때 텍스트를 포함하십시오 –

+0

'$ MODE OBJFPC'는 델파이 코드를 빠르게 포팅 할 때 이상하게 보입니다 ... –

답변

7

이 FPC의 버그처럼 보인다. 문제의 범위를 좁히려면 코드를 제거하고 최소한의 예제 만 만들어보십시오.

program project1;  
uses 
    Classes, Crt;  
type 
    TSortThread = class(TThread) 
    protected 
     procedure Execute; override; 
    public 
     constructor Create; 
    end; 

constructor TSortThread.Create; 
begin 
    inherited Create(False); 
    FreeOnTerminate := False; 
end; 

procedure TSortThread.Execute; 
begin 
end; 

var 
    SortThread : TSortThread; 
begin 
    Write('test ...'); 
    SortThread := TSortThread.Create; 
    Writeln('created'); 
    SortThread.WaitFor; 
    SortThread.Free; 
    Writeln('complete'); 
    Readln; 
end. 

및 출력이 생성 : 이것은, 예를 들어, 문제를 보여줍니다

enter image description here

이는 콘솔 출력의 버그처럼 보인다. 꽤 많은 방법으로 개선 될 수 있지만 원본 프로그램은 매트릭스를 올바르게 정렬하는 것으로 보입니다. 그럼에도 불구하고 이러한 유형의 버그는 FPC의 신뢰를 불러 일으키지 않습니다 ...

+1

어떤 버전의 FPC를 사용하고 있습니까? 트렁크 (2.7.1)로 코드를 테스트했는데 [this] (http://i.imgur.com/W2Ooipt.png)가 결과였습니다. 그것은 당신에게 자신감을 불러 일으키지는 않을지 모르겠지만 내 경험에 의하면이 버그는 발견 될 때 정말 빨리 고쳐집니다 (델파이와 달리). – Rik

+3

+1 오우 치,이 얼마나 충격! –

+0

@Rik Lazarus V1.2.4, FPC V2.6.4 사용 - 기본 컴파일 옵션, Win7-x64. 이 릴리스는 몇 개월 전입니다. –

2

@ user246408 예 오른쪽 문제는 CRT 단위입니다. 내가 사용 섹션에서 제거하고 코드가 제대로 작동하기 시작했습니다.

+5

F.Y.I. [CRT 문서] (http://freepascal.org/docs-html/rtl/crt/)에는 'The CRT unit is thread safe.'도 나와 있습니다. [이 bugtracker-entry] (http://bugs.freepascal.org/view.php?id=11554)에도 있습니다.하지만 .. 네가 알기에 쉽게 찾을 수있다. ** 문제는) – Rik

+0

@ 빅 많은 것들은 스레드 세이프가 아닙니다. 나는 "쓰레드 세이프가 아닌"*에서 "멀티 쓰레드 어플리케이션에서 사용하지 않더라도 간단히 포함될 때 치명적인 실패를 일으킨다"는 것이 꽤 큰 도약이라고 생각한다.틀 (framework) 단위 인 무언가를 위해, 나는 그 것을 모호하게 부러진 단위라고 부릅니다. –

+0

Crt (또는 내 콘솔 장치)와 같은 장치는 출력 루틴을 패치해야합니다. 그것이 단순히 "포함"이 효과를 내기에 충분한 이유입니다. –