C++ wskaźniki (pakietyzacja danych)

0

Witam,
Mam problem, z którym walczę w języku C++. Zadanie polega na podzieleniu dowolnych danych na pakiety, które składają się z nagłówka + danych. Nagłówek jest taki jak pokazuje struct header. Offset informuje o miejscu w pamięci, gdzie zaczyna się pakiet. Po nagłówku w tablicy bajtów zaczynają się dane binarnie wczytane z pliku.

  1. Alokuje następującą ilość pamięci do tablicy bajtów:
    wielkość pliku + nagłówki (ilość pakietów * sizeof(header)).
  2. Mój pomysł na czytanie danych jest następujący:
    a) Zapamiętuje adresy, gdzie zaczyna się dany pakiet w pamięci w wektorze vector<header*>.
    b) Wyrażenie (write_file_size - file_size) pokazuje aktualną ilość zapisanych danych. Jeśli dodamy do tego nagłówki zapisanych już pakietów to mamy w pamięci miejsce, gdzie będzie rozpoczynał się następny pakiet, tam powinno czytać file.read. W praktyce mogę wziąć adres aktualnego nagłówka, dodać jego sizeof i mam miejsce, gdzie mogę pisać (header_addr + sizeof(header)).
  3. Dlaczego to się kończy błędem? Gdzie namieszałem na wskaźniku, bo szukam tego parę h i nie widzę.

Ta linia wywołuje błąd:

header_addr->offset = (int) header_addr;

Wartość i = 300 w momencie wystąpienia błędu.

Pozdrawiam,

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cstdlib>

using namespace std;

struct header
{
    int offset;
    int size;
};

int main()
{
    const char *path = "E:\\uczelnia.zip";
    char* byte_array = NULL;
    int file_size;
    int write_file_size;
    int package_size = 2048;

    ifstream file;
    file.open(path, ios::binary);
    if(!file) {
        cerr << "File open error" << "\n";
        exit(1);
    }
    file.seekg(0, ios::end);
    file_size = file.tellg();
    file.seekg(0, ios::beg);
    write_file_size = file_size;

    cout << "File path: " << path << "\n";
    cout << "File size: " << file_size << "\n";
    // get number of packages
    int num_packages = file_size / package_size;
    if(file_size % package_size != 0) ++package_size;

    // allocate byte array storage in RAM
    try {
        byte_array = new char[file_size + num_packages * sizeof(header)];
    } catch(bad_alloc&) {
        cerr << "Allocation error" << "\n";
        exit(1);
    }

    vector<header*> packages;
    // point the end of last package
    header* header_addr;
    for(int i = 0; i < num_packages; ++i) {
        if(file_size >= package_size) {
            // poczatek_tablicy_bajtow + ilosc_zapisanych_bajtow + ilosc zapisanych naglowkow: prawdziwe dla i => 1
            // poczatek_tablicy_bajtow: prawdziwe dla i = 0
            if(i >= 1)
                header_addr = ( (header*) byte_array + (write_file_size - file_size) + (i + 1) * sizeof(header) );
            else
                header_addr = (header*) byte_array;
            header_addr->offset = (int) header_addr;
            header_addr->size = package_size;
            /*
             * Write package address to vector.
             */
            packages.push_back(header_addr);
            /*
             * Write data to package.
             */
            file.read((char*) header_addr + sizeof(header), package_size);
            file_size -= package_size;
        } else {
            // last package can be smaller (file_size)
        }
    }
    file.close();

    delete[] byte_array;
    return 0;
}

0

nierozwiązany problem
W linijce było:

    // get number of packages
    int num_packages = file_size / package_size;
    if(file_size % package_size != 0) ++package_size;

Powinno być:

    // get number of packages
    int num_packages = file_size / package_size;
    if(file_size % package_size != 0) ++num_packages;

Po tej poprawce program zachowuje się dokładnie tak samo, szukam dalej.

0

Przy i = 50 przerwałem dane.

Wyświetliłem offsety zgromadzone w tablicy wektorów. Różnica między pierwszym a drugim wynosi 16512. Między kolejnymi 16448. Już wiadomo dlaczego wyszedłem poza zakres tablicy. Pytanie czemu nie package_size + sizeof(header).

0
            if(i >= 1)
                header_addr = ( (header*) byte_array + (write_file_size - file_size) + (i + 1) * sizeof(header) );
            else
                header_addr = (header*) byte_array;

Po zabawie z kalkualatorem doszedłem do wniosku, że (char*) to nie to samo co (header*). Używanie wskaźników (header*) powodowało przeskakiwanie o sizeof(header) zamiast o 1 (sizeof(char)).

1 użytkowników online, w tym zalogowanych: 0, gości: 1