0

This is my code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct{
char ipaddr[20];
char filename[2048];
}iplog;

int main(){
    unsigned long numrec=0;
    iplog* e=(iplog*)calloc(1,sizeof(iplog)+1);
    iplog* p=e;
    memcpy(e->ipaddr,"127.0.0.1",20);
    memcpy(e->filename,"/bla/bla/bla",2048);
    e=(iplog*)realloc(e,sizeof(iplog)*(numrec++)+1); //memory not growing?
    e++;
    memcpy(e->ipaddr,"192.168.1.2",20);
    memcpy(e->filename,"/abc/def/ghi",2048);
    for (*p;p;p++){
        printf("IP=%s, File=%s\n",p->ipaddr,p->filename);
    }
    free(e);
    return 0;
}

What I'm trying to do is create an array of structs in RAM. I can't use the format array[n].element=value because I don't know how much memory I'll need to process all the elements so I figure reallocating the memory each time would be of benefit. When I do introduce realloc, segmentation faults happen.

Here's my logic and correct me where I make the mistake. First I allocate enough memory (via sizeof(iplog)) plus one byte for the null character. Then I send data to each element of the struct. No problems there.

I take the original allocated pointer for memory access to use inside realloc so I don't allocate hundreds of new blocks of memory chunks with their own pointers. the value of the second parameter is enough space to contain all the struct data I need. I used numrec++ to allow for this.

I then increment the data pointer ( via e++) to write data to the new space in memory.

Finally, I use the original pointer that I used to allocate memory for the first time with to try to iterate through the data in memory to print it and all I see for output is an incorrect number of lines printed along with segmentation fault as follows:

IP=, File=
IP=, File=
...
...
IP=, File=
IP=, File=
Segmentation fault

What I was expecting from the above code is this:

IP=127.0.0.1, File=/bla/bla/bla
IP=192.168.1.2, File=/abc/def/ghi

What am I doing wrong? I'm assuming it has to do with realloc?

Mike -- No longer here
  • 2,064
  • 1
  • 15
  • 37
  • You're not passing the correct size to `memcpy`. It requires the size of the *source*, not the destination. It makes a lot more sense to use `strcpy` in this case. I'm also really confused about how you're allocating memory. Why do you allocate `sizeof(iplog) + 1` bytes? What do you think `realloc` does? And what is with that `for` loop? – PC Luddite Oct 09 '15 at 03:05
  • iplog represents my struct and getting the size of it and adding a 1 allows me to allocate enough memory and I'm expecting realloc to allow me to use more memory space upon each call to it. – Mike -- No longer here Oct 09 '15 at 03:08
  • P.S. I just converted memcpy to strcpy and removed the 3rd parameter and that did not solve my problem – Mike -- No longer here Oct 09 '15 at 03:10
  • There's no need to allocate that extra byte. Only strings are null-terminated in C. And what are you allocating more space for with `realloc`? – PC Luddite Oct 09 '15 at 03:10
  • to add more of the same struct into memory – Mike -- No longer here Oct 09 '15 at 03:15
  • Noo. If you want to allocate memory for two structs, just call `malloc` two times, if you want three, call it three times, etc. Or are you trying to allocate it in a contiguous block? – PC Luddite Oct 09 '15 at 03:17
  • [don't cast the result of the `malloc` family in C](http://stackoverflow.com/q/605845/995714) – phuclv Oct 09 '15 at 04:29

4 Answers4

0

Your first problem is your use of numrec. When you go to call realloc, numrec is 0, and you are post-incrementing, meaning 0 is used here. What you really want is numrec to be 1 before the realloc (since you do have 1 record at that point), and then do a pre-increment (++numrec) so that the increment happens before being evaluated and should end up with a value of 2.

The second problem is you are allocating an extra byte in your allocations. This will mess things up when you go to do pointer arithmetic. When you do e++, this will advance e by the size of your struct, not by the size you allocated. That means you'll end up 1 byte before the 2nd struct.

The last problem is your for loop. What you should be doing is using numrec here to control your loop. The way you have it now, you are evaluating *p for no reason, then you are looping until p which is the same as saying until p != 0, which is not what you want.

MahlerFive
  • 5,159
  • 5
  • 30
  • 40
0

The line

e=(iplog*)realloc(e,sizeof(iplog)*(numrec++)+1);

is equivalent to:

e=(iplog*)realloc(e,sizeof(iplog)*(numrec)+1);
numrec = numrec + 1;

Since numrec has been initialized to 0, you are in effect, using:

e=(iplog*)realloc(e,1);

That explains the problem of segmentation fault.

Change that line to:

// You need to be able hold 2 iplog objects.
numrec = 1;
e = realloc(e,sizeof(iplog)*(++numrec)); // No need of the extra +1
                                         // No need of the explicit cast either.
R Sahu
  • 204,454
  • 14
  • 159
  • 270
0

After reading all comments and answer, I managed to make my code work now. The real issue was allocating enough memory. It turned out I was only allocating 1 byte of memory in my realloc before.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct{
char ipaddr[20];
char filename[2048];
}iplog;

int main(){
    unsigned long numrec=1,n=0;
    iplog* op=(iplog*)calloc(1,sizeof(iplog)+1);
    iplog* p,*e=op;
    strcpy(e->ipaddr,"127.0.0.1\0");
    strcpy(e->filename,"/bla/bla/bla\0");
    op=(iplog*)realloc(op,sizeof(iplog)*(++numrec)+1); //memory not growing?
    e=op;e+=(numrec-1);
    strcpy(e->ipaddr,"192.168.333.444\0");
    strcpy(e->filename,"/abc/def/ghi\0");
    op=(iplog*)realloc(op,sizeof(iplog)*(++numrec)+1); //memory not growing?
    p=op;e=op;e+=(numrec-1);
    strcpy(e->ipaddr,"111.222.1.2\0");
    strcpy(e->filename,"/abcc/defa/ghif\0");
    for (n=0;n<numrec;n++){
        printf("IP=%s, File=%s\n",p->ipaddr,p->filename);
    p++;
    }
    free(op);
    return 0;
}
Mike -- No longer here
  • 2,064
  • 1
  • 15
  • 37
0


This looks like the case for a zero length array. With this array you can allocate the needed element size when the actual array length is know.

Please see https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html

atamit81
  • 207
  • 1
  • 2
  • 7