Структура memcpy, содержащая переменные указателя на указатель void - PullRequest
0 голосов
/ 27 мая 2020

Мне нравится эта структура

struct free_bitmap{
   int *node_bitmap;
   int *data_bitmap;
}

Я хочу скопировать эту структуру в фиксированный блок памяти и записать в файл в двоичном режиме и прочитать эти данные из файла в фиксированный блок памяти. И затем скопировать эти данные с memcpy в структуру.

Вот так

struct free_bitmap f1;
struct free_bitmap f2;

f1.node_bitmap = (int *) malloc( sizeof(int) * 20 );
f1.data_bitmap = (int *) malloc( sizeof(int) * 128);

void * fblock = (void *) malloc(256);
memcpy((char*)fblock,(void*) &f1 ,256 );
int fd = open("test",O_RDWR|O_CREAT, 0600);
write(fd,fblock,256);
free(fblock);

Я могу записывать данные вот так, но я не уверен, что memcpy копирует мои переменные-указатели. И я читаю файл, но не работает.

 block = (void *) malloc(256);

lseek(fd, 0, SEEK_SET);
read(fd,fblock,256);

f2.node_bitmap = (int *) malloc( sizeof(int) * 20 );
f2.data_bitmap = (int *) malloc( sizeof(int) * 128);

memcpy((void*) &f2 , (char*)fblock , 256 ); 
free(fblock);

for(i=0;20>i;++i)
    printf("%d " ,f1.node_bitmap[i]);

free(f2.node_bitmap);
free(f2.data_bitmap);

Мой полный код здесь Нажмите

Ответы [ 2 ]

1 голос
/ 27 мая 2020

Я хочу скопировать эту структуру в фиксированный блок памяти и записать в файл в двоичном режиме и прочитать эти данные из файла в фиксированный блок памяти. А затем скопировать эти данные с помощью memcpy в структуру.

Вам действительно не нужно создавать промежуточный буфер. Просто прочтите / напишите прямо в структуру. Вы делаете это, выполняя два чтения или записи для каждой операции «сохранения / восстановления». Иногда это называют «сериализацией».

Это проще и быстрее и не требует memcpy.

Вот ваш код, отредактированный для этого:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

enum {
    NODECOUNT = 20,
    DATACOUNT = 128,
};

struct free_bitmap {
    int *node_bitmap;
    int *data_bitmap;
};

void
bitmap_alloc(struct free_bitmap *f)
{

    f->node_bitmap = malloc(sizeof(int) * NODECOUNT);
    f->data_bitmap = malloc(sizeof(int) * DATACOUNT);
}

void
bitmap_free(struct free_bitmap *f)
{

    free(f->node_bitmap);
    free(f->data_bitmap);
}

void
bitmap_write(int fd,struct free_bitmap *f)
{

    write(fd,f->node_bitmap,sizeof(int) * NODECOUNT);
    write(fd,f->data_bitmap,sizeof(int) * DATACOUNT);
}

void
bitmap_read(int fd,struct free_bitmap *f)
{

    read(fd,f->node_bitmap,sizeof(int) * NODECOUNT);
    read(fd,f->data_bitmap,sizeof(int) * DATACOUNT);
}

int
main()
{
    struct free_bitmap f1;
    struct free_bitmap f2;

    bitmap_alloc(&f1);

    int i;

    for (i = 0; i < NODECOUNT; ++i)
        f1.node_bitmap[i] = i;

    int fd = open("test", O_RDWR | O_CREAT, 0600);

    bitmap_write(fd,&f1);

    printf("a");
    lseek(fd, 0, SEEK_SET);

    bitmap_alloc(&f2);
    bitmap_read(fd,&f2);

    for (i = 0; i < NODECOUNT; ++i)
        printf("%d ", f1.node_bitmap[i]);
    printf("\n");

    bitmap_free(&f1);
    bitmap_free(&f2);

    return 0;
}

ОБНОВЛЕНИЕ:

То есть я хочу использовать этот файл как файловую систему. Например, напишите эту структуру в первый блок, а другую структуру во второй блок и размер блока 2 КБ. Поэтому я использую память кучи, чтобы исправить длину данных. Размер файла фиксированный и 1 МБ, например

Хорошо, вот версия, которая записывает несколько блоков и сравнивает результаты. Он выравнивает каждый по размеру блока 2 КБ, используя общий размер 1 МБ:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

enum {
    NODECOUNT = 20,
    DATACOUNT = 128,
    BLOCKSIZE = 2 * 1024,
    FILESIZE = 1024 * 1024,
    NMAP = 5,
};

struct free_bitmap {
    int *node_bitmap;
    int *data_bitmap;
};

void
bitmap_alloc(struct free_bitmap *f)
{

    f->node_bitmap = malloc(sizeof(int) * NODECOUNT);
    f->data_bitmap = malloc(sizeof(int) * DATACOUNT);
}

void
bitmap_free(struct free_bitmap *f)
{

    free(f->node_bitmap);
    free(f->data_bitmap);
}

void
bitmap_write(int fd,struct free_bitmap *f)
{
    ssize_t tot = 0;

    tot += write(fd,f->node_bitmap,sizeof(int) * NODECOUNT);
    tot += write(fd,f->data_bitmap,sizeof(int) * DATACOUNT);

    tot = BLOCKSIZE - tot;
    if (tot > 0)
        lseek(fd,tot,SEEK_CUR);
}

void
bitmap_read(int fd,struct free_bitmap *f)
{
    ssize_t tot = 0;

    tot += read(fd,f->node_bitmap,sizeof(int) * NODECOUNT);
    tot += read(fd,f->data_bitmap,sizeof(int) * DATACOUNT);

    tot = BLOCKSIZE - tot;
    if (tot > 0)
        lseek(fd,tot,SEEK_CUR);
}

int
mapcmp(int mapidx,const char *tag,const int *lhs,const int *rhs,int count)
{
    int i;
    int bad = 0;

    for (i = 0;  i < count;  ++i) {
        if (lhs[i] != rhs[i]) {
            printf("mapcmp: MISMATCH mapidx=%d tag=%s i=%d lhs=%d rhs=%d\n",
                mapidx,tag,i,lhs,rhs);
            bad = 1;
        }
    }

    return bad;
}

int
main(void)
{
    struct free_bitmap wlist[NMAP];
    struct free_bitmap *wcur;
    struct free_bitmap rlist[NMAP];
    struct free_bitmap *rcur;
    int off;
    int i;
    int mapidx;
    int code;

    int fd = open("test", O_RDWR | O_CREAT, 0600);
    ftruncate(fd,FILESIZE);

    // create blocks with unique test data
    off = 0;
    for (wcur = &wlist[0];  wcur < &wlist[NMAP];  ++wcur, off += 23) {
        bitmap_alloc(wcur);

        for (i = 0; i < NODECOUNT; ++i)
            wcur->node_bitmap[i] = i + off;

        for (i = 0; i < DATACOUNT; ++i)
            wcur->data_bitmap[i] = i + off + 17;

        bitmap_write(fd,wcur);
    }

    lseek(fd, 0, SEEK_SET);

    for (rcur = &rlist[0];  rcur < &rlist[NMAP];  ++rcur) {
        bitmap_alloc(rcur);
        bitmap_read(fd,rcur);
    }

    code = 0;

    // compare all data in all blocks
    for (mapidx = 0;  mapidx < NMAP;  ++mapidx) {
        wcur = &wlist[mapidx];
        rcur = &rlist[mapidx];

        if (mapcmp(mapidx,"NODE",rcur->node_bitmap,wcur->node_bitmap,NODECOUNT))
            code = 1;

        if (mapcmp(mapidx,"DATA",rcur->data_bitmap,wcur->data_bitmap,DATACOUNT))
            code = 1;
    }

    // release all blocks
    for (mapidx = 0;  mapidx < NMAP;  ++mapidx) {
        bitmap_free(&wlist[mapidx]);
        bitmap_free(&rlist[mapidx]);
    }

    printf("%s\n",code ? "FAIL" : "PASS");

    return code;
}
1 голос
/ 27 мая 2020
memcpy((char*)fblock,(void*) &f1 ,256 );

Кажется, что memcpy делает ваш код неудачным. Если вы хотите скопировать структуру, содержащую указатель (или массив), вы должны использовать memcpy для каждого параметра этой структуры. Например, если вы хотите скопировать 256-байтовую структуру для адресации, этот указатель fblock указывает на:

memcpy(fblock,f1.node_bitmap ,20*sizeof(int));
// then copy the `256-20*sizeof(int)` by of `f1.data_bitmap` to `fblock`
memcpy(((uint8_t *))fblock + 20*sizeof(int),f1.data_bitmap ,256-20*sizeof(int));
// Note that, you should initialize the data in f1.data_bitmap before copying

Если вы хотите скопировать все данные из f1.data_bitmap и f1.node_bitmap, в fblock, вы должны выделить для этого указателя не менее 128*sizeof(int) + 20 * sizeof(int) байт.

Аналогично, если вы хотите скопировать данные в f2 структуру:

memcpy((void*) &f2 , (char*)fblock , 256 ); 

Вы можете изменить на :

memcpy(f2.node_bitmap, fblock, 20*sizeof(int));
memcpy(f2.data_bitmap, (uint8_t *)fblock + 20*sizeof(int), 256 - 20 *sizeof(int));

Вы можете увидеть больше информации о копировании структуры: Копирование одной структуры в другую .

Другое дело, вы не должны приводить функцию malloc: Могу ли я привести результат mallo c?

Если код любит memcpy(fblock,f1.node_bitmap ,20*sizeof(int));, вам не нужно приводить указатель источника и назначения, потому что memcpy все равно Что касается типа данных, он заботится об адресе источника, адресе назначения и количестве данных, которые вы хотите скопировать.

...