2012-10-08 49 views

Trả lời

11

Các cuộc gọi đầu tiên phải trả lại 0; cuộc gọi thứ hai phải trả lại -1 và đặt errno thành EBADF.

Bạn nên ngăn cuộc gọi thứ hai xảy ra bằng cách đặt fd thành số không xác định đã biết, ví dụ: một -1 ngay sau khi cuộc gọi đầu tiên của close, và sau đó kiểm tra fd trước khi thực hiện cuộc gọi thứ hai (và không thực hiện cuộc gọi nếu fd-1):

close(fd); 
fd = -1; 
... 
// More code 
... 
if (fd != -1) { 
    close(fd) 
    fd = -1; 
} 

mẫu mã này sẽ giúp khi bạn cần phải thực hiện các cuộc gọi đến close từ nhiều địa điểm, nhưng bạn không chắc liệu tệp đó có đang mở hay không hoặc tệp đã được đóng chưa. Việc vượt qua -1 đến close là vô hại (bạn sẽ nhận được EBADF, tất nhiên).

+0

Tại sao bạn nên ngăn chặn cuộc gọi thứ hai xảy ra? –

+0

Đặt fd thành -1 không có hiệu lực (chắc chắn nó không "ngăn chặn cuộc gọi thứ hai xảy ra") ... cả điều đó và lệnh đóng năng suất EBADF –

+5

@JimBalter thiết lập fd thành -1 sẽ tránh được nguy cơ rất thỉnh thoảng đóng một tệp khác mà chỉ mới mở được. – simonc

7

Nó phải là vô hại, trừ khi bạn đang ren hoặc làm điều gì đó giữa hai cuộc gọi để đóng. Sau đó, bạn có thể kết thúc đóng một fd rằng một cái gì đó khác trong chương trình của bạn đã mở.

Cách luồng có liên quan là thư viện hầu như luôn làm những điều kỳ lạ sau lưng bạn. Libc sẽ mở các tập tin để tìm kiếm thông báo lỗi hoặc các công cụ phụ thuộc vào miền khác, trình phân giải có thể mở các tệp cấu hình, v.v. Nếu bạn đóng bộ mô tả tệp và đóng lại, trong môi trường luồng, bạn có thể dễ dàng kết thúc trong trường hợp tệp mô tả đã được tái sử dụng bởi một thư viện và bạn đóng nó lại sau lưng nó.

+0

+1 để đề cập các vấn đề có thể xảy ra trong môi trường luồng. – alk

+0

Cuộc gọi * đầu tiên * để đóng có thể đóng một fd từ một chuỗi khác. Hai lần đóng không liên quan đến vấn đề đó. Cách duy nhất là có liên quan ở đây là thứ hai có thể không thất bại sau khi tất cả nếu fd đó đã được mở lại, nhưng điều đó không thú vị ... nếu bạn không đồng bộ hóa chủ đề của mình, tất cả những thứ xấu có thể xảy ra. –

+2

Giá trị được trả về bởi 'open()' được hệ điều hành tái chế. Vì vậy, nếu thread A gọi là 'open()' và nhận fd = 3 thì 'close()' s nó. Sau đó, ngay trước khi luồng A gọi 'close()' lần thứ hai, luồng B được gọi là 'open()' thành công và nhận lại fd = 3. Vậy cái gì sẽ là 'close()' thứ hai được gọi bởi luồng A? – alk

1

Nếu fd giá trị pf vẫn giữ nguyên cuộc gọi thứ hai sẽ trở lại một lỗi mà các fd là không hợp lệ (EBADF - như dasblinkenlight chỉ ra)

Hãy suy nghĩ về làm somthing likg

if fd != -1) 
{ 
    close (fd); 
    fd = -1; 
} 
+1

Loại điều này là vô nghĩa, vì gần (fd) không phải là không xác định hoặc trong bất kỳ cách nào nguy hiểm khi fd đã đóng ... đóng (fd) và đóng (-1) làm chính xác điều tương tự. Lý do duy nhất để đặt fd thành -1 là đảm bảo rằng nó không phải là một bộ mô tả tệp mở hợp lệ chẳng hạn như 0. –

+0

Ok, mọi người đã lưu ý rằng một bộ mô tả tệp có thể đã được mở lại trong một chuỗi khác, vì vậy hãy đặt fd = -1 là thực hành tốt. Nhưng thử nghiệm 'fd! = -1' không thực sự cần thiết ... hiệu ứng là như nhau nếu không có nó. –

+1

Tôi đồng ý với bạn rằng thử nghiệm cho -1 là không cần thiết. Thậm chí nhiều hơn: trong một debug-build tôi sẽ bỏ qua nó, và đăng nhập lỗi 'close()' sẽ trở lại sau đó, để chỉ cho tôi mess tôi tạo ra dẫn đến đóng tập tin hai lần ... ;-) @ JimBalter – alk

3

Cuộc gọi thứ hai sẽ không thành công với Errno: EBADF khi vì lúc đó, fd không phải là bộ mô tả tệp đang hoạt động.

Nó hoàn toàn không ảnh hưởng đến việc thực thi. Tuy nhiên, nếu bất kỳ số lỗi nào được đặt bởi lần đóng đầu tiên, số đó sẽ bị mất, do đó bạn không nên đóng bộ mô tả tệp hai lần.

+0

Ah, câu trả lời này thực sự nói điều gì đó hợp lệ! +1 –

4

Đóng cùng FD hai lần nên không gây tử vong như những người khác đã chỉ ra, nhưng hãy cẩn thận mã như thế này

close(fd); 
/* ... */ 
newfd = open(....); 
/* ... */ 
close(fd); 

Đến gần thứ hai, bạn không thể chắc chắn nếu thực sự là fd giống như newfd! Điều này sẽ dẫn đến sự cố bất cứ khi nào bạn cố sử dụng newfd.

Vì vậy, (nếu có mã giữa cả hai cuộc gọi close) thì không an toàn để thực hiện việc này. Luôn luôn close mô tả tệp chính xác một lần.Luôn luôn free bộ đệm chính xác một lần.

Các vấn đề liên quan