[C/C++] probleem met file copieren met fread/fwrite

Pagina: 1
Acties:

  • Belgar
  • Registratie: Januari 2002
  • Laatst online: 17-08 22:31

Belgar

Archmaster ranzige code..

Topicstarter
Ik ben een fanatiek 'tooltjes bouwer'. Daar is mijn kennis net genoeg voor :)

Nu heb ik een programma dat geconverteerd is uit linux en met een windows GUI moet draaien. So far so good. Het probleem onstaat wanneer het programmatje gaat 'patchen'.

Het programma moet in de file een header aanbrengen en aan het uiteinde ruwe data bijvoegen.

headers|data <-----oud
headers|nieuwe header|data|nieuwe data <----- nieuw

Het programma maakt gebruik van fopen,fread, etc. Het loopt allemaal prima totdat ineens, in sommige gevallen, slechts de helft wordt weggeschreven. Het irritante is nu dat het nog nooit bij mezelf is gebeurd (XP pro). Andere gebruikers zweren echter dat het af en toe gebeurd na wat hevig patchwerk. Men krijgt geen foutmeldingen en het programma zegt dat het patchen goed is verlopen.

Ik heb al geprobeerd de size van de gecopieerde data terug te brengen, strategische flushes geplaatst en de file tussendoor sluiten en heropenen. Ik heb met een search op Google niks relevants gevonden. Het probleem blijft terug komen bij die mensen. :(

Heeft iemand een idee wat de oorzaak kan zijn? Ik heb geen invloed op wat er reeds in de file staat en wat er gepatched wordt. Wel heb ik gecontroleerd dat het niet steeds bij dezelfde file gebeurd (tenminste, niet altijd). Ik vermoedde eerst dat er ergens een EOF sequence tussen zat, maar daar zou fread toch geen probleem mee moeten hebben?

edit:

ik gebruik trouwens Borland C++ Builder 5 voor de GUI

...Als het maar werkt


  • Primal
  • Registratie: Augustus 2001
  • Laatst online: 07:47
Tja, is een beetje moeilijk om zo zonder code het goede antwoord te geven. Dan maar wat standaard vragen:

1) Worden de geopende files (zowel de file waaruit gelezen, als de file waarnaar geschreven wordt) netjes afgesloten nadat de kopieer actie is voltooid?
2) Kun je het programma debuggen?
2a) Zo ja, controleer dan wat er in de variabelen staat. Zijn dat de correcte waarden?
2b) Worden die variabelen overschreven tijdens het process?
2c) Werk je met statische variabelen die niet gereset worden na een 'patch' sessie?
2d) Worden die waarden ook daadwerkelijk goed weggeschreven?
3) Wat voor type variabelen gebruik je? Is het bereik van je variabelen niet te klein?
4) Wordt er niet geklungeld met pointers?

Antwoord eerst hier maar op, maar misschien is het handig als je toch wat meer 'insight' informatie verschaft. Of het aan je OS ligt betwijfel ik ten zeerste ...

Hoe is het programma geconverteerd? Welke libraries etc. heb je gebruikt om het onder Windows te laten lopen?

"The fastest code, is the code that is never called."


  • Belgar
  • Registratie: Januari 2002
  • Laatst online: 17-08 22:31

Belgar

Archmaster ranzige code..

Topicstarter
debuggen: dat gaat dus niet want bij mij gaat het nooit fout. Heel irritant maar echt waar. ik zal ff de code plakken:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
verentry verheader[10000]; //meer dan genoeg
int entryno,temp,i;
int copy1,copy2,copy3,copy4;
int todo,fast,oldsize;
int patchsize;
byte copy;
bool del,ren;

fseek (verdata,0,2);
oldsize=ftell (verdata);
fseek (verdata,0,0);
fread (&entryno,4,1,verdata);
for (i=0;i<entryno;i++) 
 {
   fread(&verheader[i],20,1,verdata);
 }

for (i=0;i<entryno;i++) 
 {
   verheader[i].pos=verheader[i].pos+20;
 }

patch=fopen(patchname.c_str(),"rb");
fseek (patch,0,2);
patchsize=ftell(patch);
fseek (patch,0,0);
AnsiString tempstring;
tempstring=ExtractFilePath(verdataloc);
tempstring=tempstring+"verdata.tmp";
tempfile=fopen(tempstring.c_str(),"wb");
entryno++;
fwrite(&entryno,4,1,tempfile);
entryno--;

for (i=0;i<entryno;i++) 
 {
  fwrite(&verheader[i],20,1,tempfile);
 }
verheader[entryno].type=4;
verheader[entryno].block=(Form1->vdest->Text.ToInt()+16384);
verheader[entryno].pos=(oldsize+20);
verheader[entryno].size=patchsize;
verheader[entryno].crc=1;
fwrite(&verheader[entryno],20,1,tempfile);
temp=ftell(verdata);
fflush(tempfile);

//dit gedeelte is zwaar ge-edit om het goed te krijgen zag er wat minder ranzig uit

todo=(oldsize-temp)%16;
fast=((oldsize-temp)/16);
for (i=0;i<fast;i++) 
 {
  fread(&copy1,4,1,verdata);
  fread(&copy2,4,1,verdata);
  fread(&copy3,4,1,verdata);
  fread(&copy4,4,1,verdata);
  fwrite(&copy1,4,1,tempfile);
  fwrite(&copy2,4,1,tempfile);
  fwrite(&copy3,4,1,tempfile);
  fwrite(&copy4,4,1,tempfile);
  fflush(tempfile);
 }

for (i=0;i<todo;i++) {
 fread(&copy,1,1,verdata);
 fwrite(&copy,1,1,tempfile);
 fflush(tempfile);
}

/*
for (i=temp;i<oldsize;i++) {
 fread(&copy,1,1,verdata);
 fwrite(&copy,1,1,tempfile);
}
*/


for (i=0;i<patchsize;i++) {
 fread(&copy,1,1,patch);
 fwrite(&copy,1,1,tempfile);
 fflush(tempfile);
}

fclose(verdata);
fclose (tempfile);
fclose (patch);


Sommige mensen kunnen oneindig veel toevoegen, sommige mensen nooit iets en sommige mensen krijgen problemen na bijv 10 patches. included is alleen stdio, afgezien van de Borland prut. Niemand krijgt ooit error messages. Ik val jammer genoeg in de groep personen voor wie het altijd werkt (en zo ook 70-90% van de andere gebruikers). Het programmatje wordt reeds gebruikt door enkele 100en mensen. Niet iedereen geeft feedback en niet iedereen heeft problemen. Ik moet het dus oplossen met ongeveer 5 mensen die bereid zijn elke keer nieuwe versies te proberen en daar weer op wachten. Niet ideaal en ik zelf heb geen problemen, maar ik wil het toch graag oplossen voor de anderen die het gebruiken.

...Als het maar werkt


Verwijderd

Begin maar ...
Geef deze 5 mensen een debug versie die een log file schrijft ?

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 07:40
Hele bijzondere code.

Eerst wat algemene tips:
1. Gebruik sizeof(int) in plaats van '4'; dit maakt je code beter portable en beter leesbaar.
2. Check the return values van je file functions, als je een bug vermoedt in de code! Op die manier kunnen de gebruikers met problemen in ieder geval aangeven op welke regel in welk bestand het fout gaat (mits je die info op het scherm weergeeft natuurlijk).
3. Gebruik constanten in plaats van de daadwerkelijke waarden, bijvoorbeeld SEEK_SET in plaats van (wat je nu hebt) simpelweg 0. Ook ten behoeve van de portabiliteit en leesbaarheid.

Verder lijkt het er sterk op dat je alle header entries in dezelfde bufferruimte leest. Je hebt een lus-variabele i, maar elke iteratie wordt:
code:
1
   fread(&verheader,20,1,verdata);

uitgevoerd. Ik zie niet hoe de locatie van 'verdata' gewijzigd wordt. Hetzelfde geldt trouwens voor het ophogen van de posities in de lus daarna. Ik kan me nauwelijks voorstellen dat dit voor meer dan één record gewerkt heeft; misschien heb je ontzettend veel geluk (of eigenlijk pech) gehad.

Ik heb nog geen moeite gedaan om de rest van de code door te nemen. Misschien wil je hier eerst even op reageren. Succes!

[ Voor 0% gewijzigd door Soultaker op 20-08-2002 01:52 . Reden: spelling ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01-09 21:01

.oisyn

Moderator Devschuur®

Demotivational Speaker

Soultaker schreef op 20 augustus 2002 @ 01:50:
Verder lijkt het er sterk op dat je alle header entries in dezelfde bufferruimte leest. Je hebt een lus-variabele i, maar elke iteratie wordt:
code:
1
   fread(&verheader,20,1,verdata);

uitgevoerd. Ik zie niet hoe de locatie van 'verdata' gewijzigd wordt.


er staat nog een [ i ] achter, maar dat wordt door react omgezet naar de italic tag |:(

mietje had er al melding van gemaakt: [rml][ bug] [ ] haakjes vallen soms weg, stoort in [ code]-tag[/rml]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 07:40
.oisyn schreef op 20 augustus 2002 @ 02:15:
er staat nog een [ i ] achter, maar dat wordt door react omgezet naar de italic tag |:(
Ahhh, bedankt voor die verklaring. Dat maakt 't allemaal iets redelijker. Ik zal dan maar aannemen dat sizeof(verentry) == 20 (zelfde kritiek als eerder) en de fout zit 'm dan nog niet in dat stukje.

Verwijderd

Wat doe je een hoop moeite om die gepatchte file weer over het origineel heen te kopieren zeg... Gebruik gewoon system("copy file1.dat file2.dat"), dat scheelt je een boel werk (en het is nog sneller ook).

Verder kan ik slechts bovengenoemde opmerkingen beamen en (misschien ten overvloede) het volgende zeggen :

1) gebruik DUIDELIJKE variabele namen en typen (t.b.v. leesbaarheid)
2) deel je code netjes in (gebruik evt. functies om duidelijkheid te scheppen)
3) schrijf commentaar in je code (ik maak zelf nog regelmatig mee dat ik geen snars meer van mn oude sources snap, toen ik nog dacht "ach, commentaar, ik ben toch de enige die het gebruikt, dus das nie nodig" <--- STOM!!!)
4) controleer alle returncodes van functies die zon ding teruggeven, en schrijf fouten weg in een logfile... Dit maakt het makkelijk om uit te zoeken wat er fout gaat. Maak eventueel een uitbreiding dat als de executable met -debug gestart wordt, dat ie ook ALLE operaties logt, dat maakt het mogelijk om precies uit te zoeken WAAR in de code het fout gaat (ook fouten in de code zelf kun je dan opsporen)

  • Belgar
  • Registratie: Januari 2002
  • Laatst online: 17-08 22:31

Belgar

Archmaster ranzige code..

Topicstarter
opbouwende kritiek dat wel, maar de code is dus niet helemaal van mij. Ik snap ook dus niet waar het fout kan gaan. Het commentaar zit ook niet in het origineel en de Linux versie werkt blijkbaar.

@Akhorahil het kopieren van de file gaat dus niet, omdat er op 2 verschillende plaatsen inserts gedaan worden.

Indien het iemand helpt wil ik wel extra commentaar plaatsen bij alle functies. Ik begrijp alleen niet WAAROM het fout kan gaan. Ik zal uiteraard wat extra debugs inbouwen, maar ik hoopte eigenlijk dat het een 'known issue-achtig' iets zou zijn. Mischien een handigere functie in windows om het tussenliggende gedeelte te streamen. Hoewel ik hier haast nooit post heb ik toch wel redelijk wat ervaring met programmeren.

Waarschijnlijk reageer ik zelden omdat de aanwezige C kennis op dit forum nogal overweldigend is. De meeste C++ posts haak ik af na de eerste 3 replies :). Moet voor mij ook wel een hobby blijven ;). In ieder geval bedankt voor de replies zover, ga ik maar wat uitgebreidere debug versies schrijven voor mijn Amerikaanse en Duitse vrienden.

...Als het maar werkt


  • Dash2in1
  • Registratie: November 2001
  • Laatst online: 31-08 22:49
Ik zit het door te lezen en door te lezen, maar ligt het nou aan mij of ontbreekt(-ken) er een of meerdere loopje(s) ergens of zo??

Verwijderd

Loopjes zien er goed uit volgens mij... Sorry voor die copy, maar dat bedoel ik dus met slecht leesbare code (ik dacht nl. in eerste instantie dat je de tempfile byte-voor-byte copieerde over het origineel heen nadat je klaar was met patchen)

Code lijkt toch echt correct... Ik zal nog wel ff verder kijken

Verwijderd

Zou het misschien kunnen komen doordat er gewoon stomweg te weinig diskruimte aanwezig is voor de temporary file? Je zegt nl. zelf al dat het vooral gebeurt na wat 'heftig' patchwerk...
Dat zou verklaren waarom maar de helft erop staat (de overigen fwrite's mislukken dan). Je hebt voor het patchen nl. <originele grootte> + <patchgrootte> + 20 bytes ruimte nodig...

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 07:40
Misschien is het dan een idee om vooraf de extra ruimte te reserveren (door een random stukje van de juiste grootte aan het bestand toe te voegen) en als dat lukt simpelweg binnen het bestand met data te gaan schuiven. Dat is waarschijnlijk wat efficienter dan een kopie naar een nieuw bestand maken, zeker als het om grote bestanden gaat.
Pagina: 1