Tôi có một lớp bên trong DLL của mình. Và DLL này cung cấp một "giao diện" để tạo các đối tượng của lớp này và gọi các phương thức của chúng.DLL và lớp trong ứng dụng đa luồng
Mã lớp (giản thể):
TLogger = class
private
//
public
function AddToLog(sBuf: PWideChar): Word;
constructor Create(Name: PWideChar);
destructor Destroy; override;
end;
constructor Create(Name: PWideChar);
begin
//
end;
destructor TLogger.Destroy;
begin
//
end;
function TLogger.AddToLog(sBuf: PWideChar): Word;
var
Temp1 : WideString;
Temp2 : AnsiString;
begin
Result := NO_ERRORS;
WaitForSingleObject(FMutex, INFINITE);
Temp1 := 'a';
Temp2 := Temp1;
//
ReleaseMutex(FMutex);
end;
mã DLL
function CreateLogger(LogFileName: PWideChar; PLogger: PCardinal): Word; stdcall;
begin
try
PLogger^ := Cardinal(TLogger.Create(LogFileName));
Result := NO_ERRORS;
except
Result := ERR_CREATE_OBJECT;
end;
end;
function DestroyLogger(PLogger: Cardinal): Word; stdcall;
begin
try
TLogger(PLogger).Free;
Result := NO_ERRORS;
except
Result := ERR_OBJECT_NOT_FOUND;
end;
end;
function AddToLog(PLogger: Cardinal; BufStr: PWideChar): Word; stdcall;
begin
try
Result := TLogger(PLogger).AddToLog(BufStr);
except
Result := ERR_OBJECT_NOT_FOUND;
end;
end;
Khi tôi đang cố gắng để sử dụng thư viện này từ ngày 1 chủ đề - tất cả mọi thứ là OK. Các vấn đề bắt đầu khi tôi tạo ra nhiều chủ đề gọi hàm AddToLog
với các khoảng thời gian ngẫu nhiên (mỗi luồng có đối tượng riêng của lớp đó). Trong một thời gian, tôi bắt được Access Violation
hoặc Invalid pointer operation
. Tôi đã thực hiện một số nghiên cứu và chỉ ra rằng nếu biến Temp2
có WideString
hãy nhập mọi thứ là OK. Một giải pháp khác là để di chuyển mutex vào mã thư viện (nó chỉ là một "nghiên cứu" code):
function AddToLog(PLogger: Cardinal; BufStr: PWideChar): Word; stdcall;
begin
WaitForSingleObject(TLogger(PLogger).FMutex, INFINITE);
Result := TLogger(PLogger).AddToLog(BufStr);
ReleaseMutex(TLogger(PLogger).FMutex);
end;
Giải pháp thứ hai là xấu đối với tôi bởi vì mỗi đối tượng có mutex riêng của nó (ý tưởng được rằng nếu hai đối tượng phải làm việc với một tập tin, họ có cùng một mutex để chờ đợi nhau, nếu hai đối tượng phải làm việc với các tập tin khác nhau, họ có mutexes khác nhau và làm việc song song).
Tôi đang cố gắng giải quyết vấn đề này trong 2 ngày nhưng tôi không thể hiểu điều gì sai. Làm thế nào chuỗi đúc có thể gây ra vấn đề như vậy?
Dường như với tôi rằng bạn đã xóa quá nhiều mã. Mã mà bạn có ở đây là luồng an toàn ngay cả khi bạn loại bỏ các mutex, và ngay cả khi tất cả các chủ đề được chia sẻ cùng một ví dụ của logger. Bạn cần một SSCCE. –
Bạn có đặt ['IsMultiThread'] (http://docwiki.embarcadero.com/Libraries/XE4/en/System.IsMultiThread): = True; trong DLL? –
@TOndrej Ah, tôi cá là vậy. Với 'IsMultiThread' là' False', trình phân bổ heap sẽ không phải là luồng an toàn. Tôi đề nghị bạn thêm nó như một câu trả lời. –