2011-01-26 34 views
41

thể trùng lặp:
Do I need to manually close a ifstream?tôi có cần đóng std :: fstream không?

Tôi có cần phải gọi fstream.close() hoặc là fstream một đối tượng RAII thích hợp để đóng dòng tiêu hủy?

Tôi có đối tượng địa phương std::ofstream bên trong phương thức. Tôi có thể giả định rằng tệp luôn bị đóng sau khi thoát khỏi phương thức này mà không gọi gần? Tôi không thể tìm thấy tài liệu về destructor.

+0

có nó trùng lặp. Cảm ơn bạn. Tôi đã không tìm thấy nó. –

+3

Không trùng lặp chính xác. Câu hỏi được tham chiếu dành riêng cho ifstreams và câu hỏi này nói chung về fstreams. –

Trả lời

65

Tôi nghĩ rằng các câu trả lời trước đó là gây hiểu nhầm.

fstream một đối tượng RAII thích hợp, nó không tự động đóng lại ở phần cuối của phạm vi, và có là hoàn toàn không cần bất cứ điều gì gọi close bằng tay khi đóng cửa vào cuối phạm vi là đủ.

Cụ thể, đó không phải là "thực hành tốt nhất" và không cần thiết phải xóa đầu ra.

Và trong khi Drakosha là đúng mà gọi close cung cấp cho bạn khả năng kiểm tra bit không thành công của luồng, không ai làm điều đó, anyway.

Trong một thế giới lý tưởng, người ta chỉ cần gọi stream.exception(ios::failbit) trước và xử lý ngoại lệ được ném vào một destructor của fstream. Nhưng tiếc là ngoại lệ trong destructors là một khái niệm bị hỏng trong C++ do đó, đó không phải là một ý tưởng tốt.

Vì vậy, nếu bạn muốn kiểm tra thành công của việc đóng tệp, hãy thực hiện thủ công (nhưng chỉ sau đó).

+4

Tôi thực sự kiểm tra kết quả gần như mọi lúc, bởi vì tôi đang làm việc trên một ứng dụng phải đảm bảo rằng dữ liệu được cam kết vào đĩa. Bên cạnh đó, một chút ra khỏi điểm, ** gần không đảm bảo tuôn ra ** (trên Linux ít nhất), và tôi không chắc chắn destructor không tuôn ra. Tôi thực sự nói đó là "thực hành tốt nhất" để tuôn ra và đóng cửa, và kiểm tra erros trên cả hai. – Drakosha

+7

@Drakosha: đảm bảo rằng dữ liệu được dọn dẹp tất cả các cách để đĩa là một điều hoàn toàn khác nhau từ những gì hoặc là 'flush' hoặc' close' đảm bảo. Tốt nhất bạn có thể giả định nói chung là 'flush' lấy dữ liệu ra khỏi quá trình và vào cấp hệ điều hành, ví dụ: giết chết quá trình sẽ không ngăn chặn các dữ liệu được viết. Không có API di động để đảm bảo rằng dữ liệu được cam kết lưu trữ liên tục, vì tiêu chuẩn C++ không có khái niệm lưu trữ liên tục như trái ngược với lưu trữ khác được trình bày dưới dạng một phần của hệ thống tệp. –

+1

Tôi cũng hơi ngạc nhiên bởi hành vi linux đó. Hàm hủy fstream được yêu cầu để gọi hàm 'close' thành viên,' close' được yêu cầu đóng "như thể bởi' fclose' ", và' fclose' được định nghĩa để xóa luồng. Vì vậy, các destructor chắc chắn nên tuôn ra, mặc dù đỏ bừng có thể không nhất thiết phải làm những gì bạn muốn nếu có một nguy cơ của cắm được kéo trên máy. Bạn cần (không chuẩn-C++) 'fsync' cho điều đó. –

1

Tôi nghĩ rằng đó là một thực hành tốt để đóng fstream của bạn, làm cho bạn cần phải tuôn ra bộ đệm, rằng những gì tôi đã nói với

+5

nếu fstream là một đối tượng RAII, nó sẽ bị đóng và do đó các bộ đệm được xóa sạch. Câu hỏi chính là liệu tôi có cần xử lý lỗi trên tất cả các luồng điều khiển để đảm bảo rằng nó bị xóa. –

+4

Xin lỗi, -1 chỉ vì nó bằng cách nào đó đã có +2. Phát hành tài nguyên theo cách thủ công hoặc là một dấu hiệu của chương trình xấu hoặc sự hiểu lầm về mục đích của vùng chứa. – GManNickG

+0

@GMan: Tôi cho rằng không quan tâm nếu tệp của bạn đã đóng đúng cách là trường hợp ngoại lệ và bạn nên gọi 'close()' trong hầu hết các trường hợp. * Viễn * quá nhiều nhà phát triển phần mềm đưa ra giả định rằng tôi muốn họ không về độ tin cậy và tính khả dụng của hệ thống tập tin người dùng. –

6

Để thêm vào câu trả lời của Amy Lee, nó tốt hơn để làm điều đó bằng tay vì theo cách này bạn cũng có thể kiểm tra lỗi.

BTW, theo "close" manpage:

Không kiểm tra giá trị trở lại của close() là một phổ biến tuy nhiên lỗi lập trình nghiêm trọng. Nó là khá có thể là lỗi trên một hoạt động trước đó ghi (2) được báo cáo lần đầu tiên ở cuối đóng(). Không kiểm tra giá trị trả lại khi đóng tệp có thể dẫn đến mất dữ liệu im lặng. Điều này có thể đặc biệt được quan sát với NFS và với hạn ngạch đĩa.

Mức đóng cửa thành công không đảm bảo rằng các dữ liệu đã được thành công lưu vào đĩa, như hạt nhân trì hoãn viết. Hệ thống tệp không phổ biến để xóa bộ đệm khi luồng bị đóng. Nếu bạn cần hãy chắc chắn rằng dữ liệu là vật lý sử dụng được lưu trữ fsync (2). (Nó sẽ phụ thuộc vào trên phần cứng đĩa tại thời điểm này.)

+1

Sẽ tốt hơn nếu thực hiện thủ công * nếu * bạn cần kiểm tra lỗi, điều này không có nghĩa là chúng tôi nên * luôn * đóng thủ công. Bạn không thể thực hiện một thực hành chung trong một trường hợp đặc biệt. Trong trường hợp chung, khi nó kết thúc, chúng tôi không quan tâm làm thế nào mà đã thành công, vì vậy hãy để nó đi tự động. – GManNickG

+3

@GMan: Nếu bạn không kiểm tra lỗi, điều này có nghĩa là bạn đang gây hiểu lầm cho người dùng của bạn rằng dữ liệu nằm trên đĩa trong khi nó không có. – Drakosha

+1

@Drakisha: Nhưng giống như Steve nói, một khi tôi đóng (được thực hiện tự động), lỗi hay không nó nằm ngoài tầm tay của tôi. Ngoài ra, "augment" của bạn là C++ không chuẩn, chúng ta đang nói về tiêu chuẩn 'fstream' C++ ở đây. – GManNickG

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