2016-04-04 9 views
1

Ben bir tampon içine bir ikili dosyadan verilerin bir parça okumak ve daha sonra tampon içinde yapılar depolamak için tampon farklı lokasyonlarda işaretçileri yerleştirmek istiyorum. Ancak, bu yöntemi denediğimde, muhtemelen işaretçileri yerleştirdiğim için yanlış veriyi geri alıyorum.Bir ikili dosyayı bir arabelleğe nasıl okur ve sonra bunları başlatmak için farklı noktalardaki struct pointer'larımı seçerim?

Not: readEntry ve writeThis, yerleşik olan hatayı yakalama ile sadece düşük seviyeli read() ve write() 'dır. ReadEntry, dosyanın sonuna ulaştığında programı sonlandırır. BUF

arasında

#define BUF 64 

struct my_struct 
{ 
    int num; 
}; 

my_struct ve tanımı

int i; 
char buffer[BUF]; 
struct my_struct *m = (struct my_struct *) malloc(sizeof(struct my_struct)); 

for(i=0; i<4; i++) 
{ 
    m->num = i; 
    printf("Initializing m->num to %d\n", m->num); 
    writeThis(fd, &m, sizeof(struct my_struct)); 
} 

lseek(fd, 0, SEEK_SET); 

while(1) 
{ 
    printf("Read\n"); 
    readEntry(fd, buffer, (sizeof(struct my_struct)*4)); 
    m = (struct my_struct *) buffer; 
    printf("num = %d\n", m->num); 
    m = (struct my_struct *) buffer+(sizeof(m)); 
    printf("num = %d\n", m->num); 
    m = (struct my_struct *) buffer+((sizeof(m)*2)); 
    printf("num = %d\n", m->num); 
    m = (struct my_struct *) buffer+((sizeof(m)*3)); 
    printf("num = %d\n", m->num); 
} 
return 0; 

writeThis()

void writeThis(int fd, void *buffer, int writeAmt) 
{ 
    if (write(fd, buffer, writeAmt) != writeAmt) 
    { 
     fprintf(stderr, "Error writing\n"); 
     exit(-1); 
    } 
} 

readEntry()

void readEntry(int fd, void *buffer, int writeAmt) 
{ 
    if (read(fd, buffer, writeAmt) != writeAmt) 
    { 
     printf("Finished reading\n"); 
     free(buffer); 
     exit(0); 
    } 
} 

I sizeof (yapı my_struct) almak için geri 4

Çıktı:

Initializing m->num to 0 
Initializing m->num to 1 
Initializing m->num to 2 
Initializing m->num to 3 
Read 
num = 134524936 
num = -1208081680 
num = -1209552416 
num = 1111804576 
Read 
Finished reading 

HexDump

00000000 10 b4 04 08 10 b4 04 08 10 b4 04 08 10 b4 04 08 |................| 
00000010 
+0

'char' da bir ekspresyon olmayan Çeşidi' char' veya karakter yazın. – EOF

+0

'char buffer = malloc (BUF);' ile sigortalanmasını tavsiye edin ve 'm' aynı hizaya getirin. - veya hizalamayı sağlamak için başka bir yaklaşım kullanın. Şimdi olduğu gibi m = (struct my_struct *) buffer, 'muhtemelen UB'dir. – chux

+0

BTW: insure 'BUF> = sizeof (struct my_struct) * 4'. – chux

cevap

1

Bazı temizlenmiş denenmemiş kodu - problemlere düzeltmeleri için açıklama bakın. 2 büyük olanlar gerekmediğinde ve işaretçi aritmetiği olduğunda &'dur. kullanmadan önce malloc() dönüş sonucu denetlemek

#define BUF 64 

struct my_struct { 
    int num; 
}; 

int i; 

// Suggest `malloc()` rather than `char buffer[BUF]`. 
// The issues is _alignment_, perhaps that is new for you. 
char *buffer = malloc(BUF); 

// Cast not needed. Better to use size of variable, than sizeof type. 
// Think how easy this is to maintain code should `m` take on a new type. 
// struct my_struct *m = (struct my_struct *) malloc(sizeof(struct my_struct)); 
struct my_struct *m = malloc(sizeof *m); 

for(i=0; i<4; i++) { 
    m->num = i; 
    printf("Initializing m->num to %d\n", m->num); 
    // & not needed here. `m` is the pointer to the place to read data 
    // writeThis(fd, &m, sizeof(struct my_struct)); 
    // Use size of variable 
    writeThis(fd, m, sizeof *m); 
} 

lseek(fd, 0, SEEK_SET); 

while(1) 
{ 
    printf("Read\n"); 
    // Again, use sizeof the variable, rather than size of type 
    //readEntry(fd, buffer, (sizeof(struct my_struct)*4)); 
    readEntry(fd, buffer, sizeof *m *4); 
    m = (struct my_struct *) buffer; 
    printf("num = %d\n", m->num); 

    // do not cast and then add to char * 
    // add and then cast 
    // m = (struct my_struct *) buffer+(sizeof(m)); 
    m = (struct my_struct *) (buffer+(sizeof(*m)); 
    // OR, add after the cast, but only add 1 
    m = (struct my_struct *) buffer + 1; 

    printf("num = %d\n", m->num); 
    m = (struct my_struct *) buffer+2; 
    printf("num = %d\n", m->num); 
    m = (struct my_struct *) buffer+3; 
    printf("num = %d\n", m->num); 

    // You could have an infinite loop here, need a reason to exit 
} 
free(buf); 

return 0; 

Sağlam kod

Belleği sızıntı ve tip bir nesne erişerek tanımsız davranış neden olan
+0

SAYESİNDE (* unuttum)! Bu hile yaptı! Ama neden tamponlama işine sadece bir tane eklediniz? Herzaman sizeof * m baytları arabelleğe yazmıyor mu? –

+0

@OP 'm = (struct my_struct *) buffer + (sizeof (m));' bir 'eksik ('. – chux

+0

@OP '(struct my_struct *) (buffer + (sizeof (* m))' ekler ne '' m 'noktaları için;' * bir 'yapı my_struct 1 "kat' sizeof yapı my_struct'"' (m = yapı my_struct *) tamponu + 1 'a char * kez' sizeof char'. 'ekler" Araştırma işaretçisi aritmetiği. – chux

İlgili konular