Autor Téma: setlength a Access violation  (Přečteno 138 krát)

Offline vangog

  • Plnoletý
  • ***
  • Příspěvků: 114
  • Karma: 0
    • Verze Delphi: 7
setlength a Access violation
« kdy: 11-07-2018, 12:25:48 »
Mám nadeklarováno:
i, os1, os2: integer;
data,item: TBytes;

Ze souboru s řetězcem 'AhojJakSeMáteDnesJe10.7.14:00' Parsuju slovíčka po offsetech.

V cyklu navyšuju i od 0 do n. Nastavuju velikost pole:

Kód: Delphi [Vybrat]
  1. setlength(item, os2-os1);
  2. move(data[os1], item[1], os2);
  3.  

Tabulka hodnot:
i
os2
os1
výsledek
0
4
0
4
1
7
4
3
2
9
7
2
3
13
9
4
4
17
13
4
5
19
17
2
6
24
19
5

Na posledním řádku při i=6 mi ale setlenght krache s chybou Access Violation.

Čím to může být?
« Poslední změna: 11-07-2018, 12:51:16 od vangog »

Offline Delfin

  • Guru
  • *****
  • Příspěvků: 950
  • Karma: 43
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Re:setlength a Access violation
« Odpověď #1 kdy: 11-07-2018, 12:30:12 »
Kód: Delphi [Vybrat]
  1. setlength(item, os2-os1);
  2. move(data[os1], item[1], os2);

Kód: Delphi [Vybrat]
  1. setlength(item, os2-os1); // nastavis velikost na os2-os1
  2. move(data[os1], item[1], os2); // kopirujes data o velikosti os2

Tudiz v te iteraci nastavis velikost bufferu na 5 bajtu a snazis se kopirovat 24 bajtu.
I'm a soldier, so don't panic! I know the underground! No more Google, go duck, go!

Offline vangog

  • Plnoletý
  • ***
  • Příspěvků: 114
  • Karma: 0
    • Verze Delphi: 7
Re:setlength a Access violation
« Odpověď #2 kdy: 11-07-2018, 12:43:26 »
Kód: Delphi [Vybrat]
  1. setlength(item, os2-os1);
  2. move(data[os1], item[1], os2);

Kód: Delphi [Vybrat]
  1. setlength(item, os2-os1); // nastavis velikost na os2-os1
  2. move(data[os1], item[1], os2); // kopirujes data o velikosti os2

Tudiz v te iteraci nastavis velikost bufferu na 5 bajtu a snazis se kopirovat 24 bajtu.

To je asi dobrý postřeh, ale krachne to setlength, nikoliv move.

Edit:
Ještě jakým způsobem připravuji pole data:

Kód: Delphi [Vybrat]
  1.     try
  2.       fsInput := TFileStream.Create(fileName, fmOpenRead);
  3.  
  4.       try
  5.         filesize := fsInput.size;
  6.         setlength(content, filesize);
  7.         fsInput.ReadBuffer(content[0], filesize);
  8.  
  9.         // get items Count & dataStart
  10.         move(content[1],itemsCount, offsetsize );
  11.         move(content[3],dataStart, offsetsize );
  12.  
  13. .... (zkráceno) ...
  14.  
  15. // get data
  16. dataSize := filesize-dataStart-datalen;
  17. setlength(data, dataSize);
  18. // @EDIT data[0] to data[1]
  19. move(content[dataStart-datalen],data[1], dataSize);
  20.  
« Poslední změna: 11-07-2018, 12:53:05 od vangog »

Offline vangog

  • Plnoletý
  • ***
  • Příspěvků: 114
  • Karma: 0
    • Verze Delphi: 7
Re:setlength a Access violation
« Odpověď #3 kdy: 11-07-2018, 17:42:38 »
Ze začátku jsem měl dost chyb ohledně pointerů, já totiž předpokládal že ty čísla se budou zapisovat do souboru např. takto:
0000 0019 (číslo vlevo počet položek, číslo vpravo, kde začínají data)
a tomu jsem přizpůsobil ty indexy.

Když jsem si přečetl

Citace
Dynamic arrays (any array that you can call SetLength on, as opposed to declaring its bounds at compile time like array[1..5] of integer) are indexed starting from 0, not from 1. So by treating your array as if it used 1-based indexing instead of 0-based indexing, you're overflowing the bounds of the array and trying to write to memory that's not allocated to you, which can cause an access violation.

Tak jsem to poopravoval, vypomohl jsem si konstantama, abych se v kódu lépe vyznal.

Kód: Delphi [Vybrat]
  1. // Constants related to TBytes:
  2. const IOD_bytesBeforeItem = 0; // bytes describing word item
  3. const IOD_itemsNoIndex = 0; // items count index
  4. const IOD_dataIndex = 2; // start of data index
  5. const IOD_headerIndex = 0; // start of header
  6. const IOD_offsetsIndex = 4; // start of offsets section
  7. const IOD_contentIndex = 0; // start of the file
  8. const IOD_dataProvLen = 0; // when header was initially created it contains one byte of data
  9.  
Ten problém jsem tedy vyřešil, ale objevil se jiný problém ve funkce ReadFile.


Kód: Delphi [Vybrat]
  1. filesize := fsInput.size;
  2. setlength(content, filesize);
  3. fsInput.ReadBuffer(content[IOD_contentIndex], filesize);
  4.  
  5. // get items Count & dataStart
  6. move(content[IOD_headerIndex+IOD_itemsNoIndex],itemsCount, offsetsize );
  7. move(content[IOD_headerIndex+IOD_dataIndex],dataStart, offsetsize );
  8.  
  9. // get header
  10. headerSize := dataStart-datalen;
  11. setlength(header, headerSize);
  12.  
  13. // get offsets - ONLY IF DATA ARE IN FILE
  14. if itemsCount>0 then
  15.   begin
  16.     offsets_size := itemsCount * offsetSize;
  17.     setlength(offsets, offsets_size);
  18.  
  19. {  @ZJISTI PROČ SE NEZKOPÍRUJÍ VŠECHNY OFFSETY
  20.     Z HLAVIČKY. MÍSTO 16 JE JICH JEN 8 }
  21.  
  22.     move(content[IOD_offsetsIndex],offsets[0], offsets_size );
  23.  

Takže jak koment napovídá, nemohu přijít na to proč se nedaří zkopírovat ty offsety.

Data v souboru:
0800 1800 0000 0400 0700 0900 0D00 1100 1300 1800 1D00 0000
6168 6F6A 6A61 6B73 656D 6174 6564 6E65 736A 6531 302E 372E 3134 3A30 30

Datová část je zobrazena podtrženě.
Tučně je počet položek a datový offset.
0000 tučně je poslední volné místo v hlavičce pro zápis offsetu.

offsets vratí toto:
(0, 4, 7, 9, 13, 17, 19, 24, 0, 0, 0, 0, 0, 0, 0, 0)
podle mě by snad mělo být toto:
AhojJakSeMáteDnesJe10.7.14:00
(0,4, 7, 9, 13, 17, 19, 24, 0, 0, 0, 0, 0, 0, 0, 0)
« Poslední změna: 11-07-2018, 17:45:57 od vangog »

Offline vangog

  • Plnoletý
  • ***
  • Příspěvků: 114
  • Karma: 0
    • Verze Delphi: 7
Re:setlength a Access violation
« Odpověď #4 kdy: 11-07-2018, 23:14:14 »
Tak jsem to vyřešil. Chybu jsem udělal v tom, že jsem si úplně popletl co je offsets, zacházel jsem s tím jako s polem bytů, přitom to bylo pole wordů určené ne ke kopírování, ale jako přehled offsetů.

Offline Delfin

  • Guru
  • *****
  • Příspěvků: 950
  • Karma: 43
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Re:setlength a Access violation
« Odpověď #5 kdy: 12-07-2018, 09:50:30 »
Za me uz :-X Stale vsak zasnu jak si nekdo muze hazet klacky pod nohy vlastnim binarnim formatem s ofsety textu pricemz se cte a prepisuje vzdy cely soubor.
I'm a soldier, so don't panic! I know the underground! No more Google, go duck, go!

 

S rychlou odpovědí můžete používat BB kódy a emotikony jako v běžném okně pro odpověď, ale daleko rychleji.

Jméno: E-mail:
Ověření:
Kolik je šest plus čtyři (slovem):