2014-09-21 4 views
4

Прежде всего я хотел бы показать вам мой код:Multithreaded bubblesort. Прекрасно работает с delphi 7, но не с Lazarus? Ошибка компилятора?

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. 

Когда я скомпилировать этот код и работать с Delphi 7 она работает нормально. Но когда я скомпилирую его с Lazarus, последний текст «writeln» удваивается или утроится, а программа зависает. Может ли кто-нибудь сказать мне, почему?

Delphi 7 является правильным: Delphi 7

Лазарь не является правильным: Lazarus

+0

Можете ли вы показать результат, который вы наблюдаете, и объяснить, какой результат вы ожидаете. Я также задаюсь вопросом, почему вы объявляете 'PIntegerArray'. Удалите это и на его месте используйте 'TIntegerArray', который уже является ссылкой. –

+0

Что касается вашего редактирования, вам не нужно загружать изображения. Включите текст, после всего этого консольного приложения –

+0

'$ MODE OBJFPC' выглядит странно, когда быстро переносит код Delphi ... –

ответ

7

Это похоже на ошибку в ФФК. Чтобы сузить проблему, она часто помогает устранить код и попытаться создать минимальный пример. Это, например, демонстрирует проблему:

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). Это может не внушить доверия для вас, но в моем опыте такие ошибки исправляются очень быстро, когда их обнаруживают (в отличие от Delphi). – Rik

+3

+1 Ой, какой шокер! –

+0

@Rik Использование Lazarus V1.2.4, FPC V2.6.4 - параметры компиляции по умолчанию, Win7-x64. Этот выпуск всего несколько месяцев. –

2

@ user246408 Да, проблема связана с CRT. я удалил его из раздела uses, и код начал работать правильно.

+5

F.Y.I. В [документации CRT] (http://freepascal.org/docs-html/rtl/crt/) также указано: «ЭЛТ-блок не является потокобезопасным». Это также в [this bugtracker-entry] (http://bugs.freepascal.org/view.php?id=11554) ... но, да ... это легко найти, если вы ** знаете ** проблема с CRT;) – Rik

+0

@Rik Многие вещи не являются потокобезопасными. Я думаю, что это довольно большой скачок, чтобы перейти от * «not threadsafe» * к * »вызывает катастрофический сбой, когда он просто включается, даже если он не используется, в многопоточном приложении» *.Для чего-то, что является структурной единицей, я бы назвал это недвусмысленно сломанной единицей. –

+0

Такие устройства, как Crt (или мой консольный блок), должны исправлять выходные процедуры. Вот почему «просто в том числе» достаточно, чтобы заставить его иметь эффект. –