2012-12-12 21 views
9

Tôi thấy rằng trong VS2010, hàm seekg không hoạt động đúng khi tệp chính xác là 4294967295 byte được mở.seekg không thể xử lý tệp của 4294967295 byte đúng

Tôi đang sử dụng mã đơn giản:

#include <iostream> 
#include <fstream> 
using namespace std; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    std::ifstream file; 

    // cmd: fsutil file createnew tmp.txt 4294967295 
    file.open(L"c:/tmp.txt", ifstream::in | ifstream::binary); 

    if(!file.is_open()) 
     return -1; 

    file.seekg(0, std::ios::end); 

    auto state = file.rdstate(); 

    // this condition shoots only when size of the file is equal to 4294967295 
    if((state & ifstream::failbit)==ifstream::failbit) 
    { 
     std::cout << "seekg failed"; 
    } 

    // after seekg failed, tellg returns 0 
    std::streampos endPos = file.tellg(); 

    return 0; 
} 

Cùng mã với các file của 4294967294 và 4294967296 đang làm việc mà không cần bất kỳ vấn đề.

Có ai đó biết giải pháp cho vấn đề này không?

Cập nhật:

Dường như vấn đề nằm ở đây:

template<class _Statetype> 
class fpos 
{ 
__CLR_OR_THIS_CALL operator streamoff() const 
{ // return offset 
return ((streamoff)(_Myoff + _FPOSOFF(_Fpos))); 
} 
} 

chính xác tại

_FPOSOFF(_Fpos) 

nơi

#define _FPOSOFF(fp) ((long)(fp)) 

Vì vậy, phải mất 4294967295 và chuyển đổi nó thành -1!

Nói cách khác nói, mã như vậy sẽ thất bại

//returns -1, even if sizeof(fpos_t)=8 
fpos_t pos = _FPOSOFF(4294967295); 

_Myoff, _Fpos, streamoffset là 64bit

Tại sao họ làm chuyển đổi này nếu tất cả các loại là 64 bit !? Tôi không có ý tưởng))

+1

Lưu ý: 4294967295 là 0xffffffff. Có lẽ một số mã 32 bit ở đâu đó đang phá vỡ. – ecatmur

+1

Cho rằng 4294967295 là mẫu bit giống như -1, nó sẽ không làm tôi ngạc nhiên nếu đây là một lỗi trong thời gian chạy. Tôi sợ tôi không có một workaround để cung cấp mặc dù ... – NPE

+1

Đây là một lỗi và được cố định trong Visual Studio 2012: '_FPOSOFF' bây giờ phôi thành' long long' và do đó tránh cắt ngắn. –

Trả lời

4

Đây thực sự là lỗi trong Visual C++ 2010. Báo cáo trên Microsoft Connect cách đây hai năm: "std::fstream use 32-bit int as pos_type even on x64 platform" (tiêu đề của lỗi không đúng; các triệu chứng thực sự gây ra bởi lỗi này trong _FPOSOFF).

lỗi này được cố định trong Visual C++ 2012, trong đó _FPOSOFF được định nghĩa là:

#define _FPOSOFF(fp) ((long long)(fp)) 

Bạn sẽ được khuyên để nâng cấp lên Visual C++ 2012 nếu bạn có thể làm như vậy.

+0

Cảm ơn bạn, tôi cũng sẽ kiểm tra nó trên VS2012, nhưng không phải lúc nào cũng dễ dàng chuyển sang một IDE khác. – Rusty

7

Thực hiện luồng nội bộ có một const '_BADOFF' bằng 0xffffffff, được trả lại khi tìm kiếm thất bại. Trong trường hợp này, tìm kiếm thành công, nhưng giá trị trả về từ tìm kiếm bằng với mã lỗi, dẫn đến trình bao bọc luồng thiết lập sai mã của nó sai.

_BADOFF được định nghĩa là loại 64 bit, nó chỉ được gán một giá trị ngu ngốc.

Giải pháp thay thế, bạn có thể tìm kiếm 1 byte ngắn và sau đó đọc một byte.

file.seekg(-1, std::ios::end); 
char temp; file >> temp; 

Tuy nhiên, vẫn có thể xảy ra sự cố với tệp lớn hơn nếu bạn tìm chúng ở vị trí ngẫu nhiên. Ví dụ: nếu tệp của bạn lớn hơn một byte, tìm kiếm -1 này sẽ không thành công, vì vậy đây không phải là giải pháp chung.

OP đã mở rộng câu hỏi của họ, vì vậy tôi sẽ mở rộng câu trả lời của mình. Có, giá trị tìm kiếm được truyền bằng cách sử dụng chuyển đổi không an toàn trước khi so sánh. Điều này dường như không ảnh hưởng đến khả năng tìm kiếm vượt quá điểm đó trong tệp, vì nó chỉ được sử dụng để so sánh với giá trị lỗi - luồng vẫn có độ lệch bên phải trong nó. Tuy nhiên nó dường như là nguyên nhân gốc rễ của _BADOFF bị nghi ngờ ngay từ đầu, vì _BADOFF được đặt là '-1' trong mã nguồn, và sẽ bị chuyển đổi tương tự, cắt ngắn thành 0xffffffff. Vì vậy, sửa chữa cho libs có thể là để sửa chữa các diễn viên (giả sử không có tác dụng phụ khác làm như vậy), nhưng vì lợi ích của việc làm xung quanh vấn đề, bạn chỉ phải tránh tìm kiếm vị trí nơi 32 bit dưới cùng được đặt. Nó sẽ tìm kiếm vượt ra ngoài OK, từ những gì tôi có thể nhìn thấy.

+4

WTF (Thất bại tuyệt vời) –

+0

Tuyệt vời? Shirley bạn có nghĩa là "khủng khiếp"? –

+3

Anh ấy có nghĩa là Triumphant và không gọi anh ấy là Shirley –

0

Tại thời điểm này có hai giải pháp không phải là rất thoải mái

  1. Thực hiện một sửa chữa trong stdio.h

    #define _FPOSOFF (fp) ((lâu dài) (fp))

  2. Di chuyển đến VS2012 (mà cũng là buồn)

    Đây là một lỗi và được cố định trong Visual Studio 2012: _FPOSOFF bây giờ phôi dài và do đó> tránh cắt ngắn. - James McNellis

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