2012-12-12 6 views
9

Ich habe festgestellt, dass in SE2010, seekg Funktion nicht ordnungsgemäß funktioniert, wenn Datei von genau 4294967295 Bytes geöffnet ist.seekg kann nicht Datei von 4294967295 Bytes richtig behandeln

Ich bin mit einfachen Code:

#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; 
} 

Denselben Code mit Dateien von 4294967294 und 4294967296 ist ohne Probleme arbeiten.

Kennt jemand eine Lösung für dieses Problem?

Update:

Es ist wie dieses Problem sieht liegt hier:

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

genau an

_FPOSOFF(_Fpos) 

wo

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

Also dauert es 4294967295 und konvertiert es in -1!

Mit anderen Worten gesagt, wird ein solcher Code

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

_Myoff, _Fpos scheitern, streamoffset 64bit sind

Warum sie diese Umwandlung, wenn alle Arten 64-Bit sind !? Ich habe keine Ahnung))

+1

Hinweis: 4294967295 ist 0xffffffff. Wahrscheinlich gibt es irgendwo einen 32-Bit-Code, der kaputt geht. – ecatmur

+1

Angesichts 4294967295 ist das gleiche Bitmuster wie -1, es würde mich nicht überraschen, wenn dies ein Fehler in der Laufzeit war. Ich habe Angst, dass ich keinen Workaround anbieten kann ... – NPE

+1

Dies ist ein Fehler und wird in Visual Studio 2012 behoben: '_FPOSOFF' wird jetzt zu' long long' umgewandelt und vermeidet so die Kürzung. –

Antwort

4

Dies ist in der Tat ein Fehler in Visual C++ 2010. Es wurde vor zwei Jahren auf Microsoft Connect gemeldet: "std::fstream use 32-bit int as pos_type even on x64 platform" (der Titel des Fehlers ist falsch; die Symptome wurden tatsächlich von diesem Fehler in _FPOSOFF verursacht).

Dieser Fehler ist in Visual C++ 2012 festgelegt, wobei _FPOSOFF wie folgt definiert ist:

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

Sie würden gut zu Visual C++ 2012 aktualisieren beraten, wenn Sie in der Lage sind, dies zu tun.

+0

Danke, ich wollte es auch auf VS2012 überprüfen, aber es ist nicht immer einfach, zu einer anderen IDE zu wechseln. – Rusty

7

Intern hat die Stream-Implementierung eine const '_BADOFF', die gleich 0xffffffff ist, die zurückgegeben wird, wenn die Suche fehlgeschlagen ist. In diesem Fall ist die Suche erfolgreich, aber der zurückgegebene Wert von der Suche ist gleich dem Fehlercode, was dazu führt, dass der Datenstrom-Wrapper fälschlicherweise seinen Fehlercode einstellt.

_BADOFF ist als 64-Bit-Typ definiert, es wurde gerade ein dummer Wert zugewiesen.

Als Workaround können Sie 1 Byte kurz suchen und dann ein Byte lesen.

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

weisen jedoch darauf hin, dass dieser Fehler jederzeit manifestieren wird, dass bestimmte Datei-Offset seek'd zu, so könnte es immer noch ein Problem für größere Dateien, wenn Sie in ihr zu zufälligen Orten suchen. Zum Beispiel, wenn Ihre Datei ein Byte größer wäre, würde diese -1 Suche fehlschlagen, also ist dies keine allgemeine Lösung.

Die OP hat ihre Frage erweitert, also werde ich meine Antwort erweitern. Ja, der Suchwert wird vor dem Vergleich mithilfe einer unsicheren Konvertierung umgewandelt. Dies scheint die Möglichkeit nicht zu beeinträchtigen, über diesen Punkt hinaus in der Datei zu suchen, da es nur zum Vergleich mit dem Fehlerwert verwendet wird - der Stream hat immer noch den richtigen Offset. Es scheint jedoch, dass die Hauptursache von _BADOFF in erster Linie zweifelhaft ist, da _BADOFF in der Quelle auf '-1' gesetzt ist, und wird die gleiche Umwandlung erleiden, die auf 0xffffffff abgeschnitten wird.

Also könnte die Korrektur für die Bibliotheken darin bestehen, die Besetzung zu korrigieren (vorausgesetzt, es gibt keine anderen Nebeneffekte), aber um das Problem zu umgehen, müssen Sie nur vermeiden, Positionen zu suchen untere 32-Bit sind gesetzt. Es wird danach suchen, was ich sehen kann.

+4

WTF (Was für ein schrecklicher Fehler) –

+0

Großartig? Shirley, du meinst "Schrecklich"? –

+3

Er bedeutet triumphierend und nennen ihn nicht Shirley –

0

In diesem Moment gibt es zwei nicht sehr schön Lösungen

  1. Machen Sie ein Update in der stdio.h

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

  2. Umzug in VS2012 (die auch traurig ist)

    Dies ist ein Fehler und ist in Visual Studio 2012 behoben: _FPOSOFF wird jetzt zu lange lange umgewandelt und so> vermeidet die Kürzung. - James McNellis

Verwandte Themen