c - Writing struct + write(buf) points to uninitialised byte(s) -


i allocating space struct node in variable n0. save struct file using fwrite, when run valgrind error. code below, me please?

==1412== syscall param write(buf) points uninitialised byte(s) ==1412==    @ 0x4f22870: __write_nocancel (syscall-template.s:81) ==1412==    0x4eb0002: _io_file_write@@glibc_2.2.5 (fileops.c:1261) ==1412==    0x4eb14db: _io_do_write@@glibc_2.2.5 (fileops.c:538) ==1412==    0x4eb0d5f: _io_file_close_it@@glibc_2.2.5 (fileops.c:165) ==1412==    0x4ea4b0f: fclose@@glibc_2.2.5 (iofclose.c:59) ==1412==    0x400793: main (in /home/grados-sanchez/git/merkle-codigos-c/test_file) ==1412==  address 0x402500c not stack'd, malloc'd or (recently) free'd ==1412==  uninitialised value created stack allocation ==1412==    @ 0x40073f: main (in /home/grados-sanchez/git/merkle-codigos-c/test_file)  typedef struct {     unsigned char * ustr;     int height; }node;  void node_init(node * n, int r) {      int i;     n->ustr = malloc((r + 1) * sizeof(unsigned char));     (i = 0; < r; i++) {         (n->ustr)[i] = random() & 0xff;     }     (n->ustr)[r] = 0;     n->height = -1; } void node_destroy(node * n) {     free(n->ustr);     n->height = -1; }  int main() {     file* file_ptr = fopen("file1", "w+");     node n0;     node_init(&n0,2);     fwrite(&n0, sizeof(node), 1, file_ptr);     fclose(file_ptr);     node_destroy(&n0);     return 0; } 

this happens because compiler padding struct , you're writing padding bytes not initializing them. can see first running program, , examining comes out:

$ od -x file1 0000000 92c0 04c2 0000 0000 ffff ffff 0000 0000 0000020 

the first 8 bytes (92c0 04c2 0000 0000) pointer value, ustr (note it's writing value of pointer itself, not points to, may not intended, that's separate issue).

the next 4 bytes (ffff ffff) int height set -1.

and there 4 more bytes set 0. these padding inserted compiler did not initialize. can prove case modifying program make padding explicit:

typedef struct {     unsigned char * ustr;     int height;     int pad; }node;  void node_init(node * n, int r) {      int i;     n->ustr = malloc((r + 1) * sizeof(unsigned char));     (i = 0; < r; i++) {         (n->ustr)[i] = random() & 0xff;     }     (n->ustr)[r] = 0;     n->height = -1;     n->pad = 0xdeadbeef; } 

if run program now, first of valgrind warning goes away, , second file contents show:

$ od -x file1 0000000 92c0 04c2 0000 0000 ffff ffff beef dead 0000020 

the value of pad variable shows in place of previous zeros.

this happens because compiler trying make size of struct multiple of machine's word size, in case appears 8 bytes (64 bits).

you don't want include superfluous pad variable, other option suppress warning clear entire struct start:

typedef struct {     unsigned char * ustr;     int height; }node;  void node_init(node * n, int r) {      int i;      /* clear node struct suppress valgrind warnings */     memset(n, 0, sizeof(node));     n->ustr = malloc((r + 1) * sizeof(unsigned char));     (i = 0; < r; i++) {         (n->ustr)[i] = random() & 0xff;     }     (n->ustr)[r] = 0;     n->height = -1; } 

this suppresses valgrind warning because initializing padding bytes, , contents of bytes in file go 0, except you're explicitly setting them rather relying on default initialization:

$ od -x file1 0000000 92c0 04c2 0000 0000 ffff ffff 0000 0000 0000020 

edit:

one other experiment make clear. add following main() , run again:

printf("sizeof unsigned char *: %d\n", sizeof(unsigned char *)); printf("sizeof int: %d\n", sizeof(int)); printf("sizeof node: %d\n", sizeof(node)); 

on 64-bit intel linux see:

$ ./writer  sizeof unsigned char *: 8 sizeof int: 4 sizeof node: 16 

the struct larger sum of parts , writing whole thing, initializing part.

edit 2:

in response comment below fixing issue pointer being written rather points to, can address writing fields of struct individually rather writing whole struct itself. incidentally, fix original valgrind problem in different way, because no longer writing padding bytes. main end looking this:

int main() {     file* file_ptr = fopen("file1", "w+");     node n0;     node_init(&n0,2);     fwrite(n0.ustr, strlen(n0.ustr), 1, file_ptr);     fwrite(&n0.height, sizeof(n0.height), 1, file_ptr);     fclose(file_ptr);     node_destroy(&n0);      return 0; } 

and if run , @ file, no longer contains 8 byte pointer, 2 bytes of data points to:

$ od -x file1  0000000 c667 ffff ffff 0000006 

Comments

Popular posts from this blog

asp.net mvc - SSO between MVCForum and Umbraco7 -

Python Tkinter keyboard using bind -

ubuntu - Selenium Node Not Connecting to Hub, Not Opening Port -