freeing specific element of struct pointer - C - c

I have a struct let say
struct packets {
int tcp_source;
int tcp_dest;
char *ip_source;
char *ip_dest;
int seq;
...
} *pkts;
I am allocating space using malloc in while loop and inside while loop when I done using specific pkts (in pointed to by (ptks+index)) I need to free it like this:
while (i++ < n - 1) {
(pkts+i)=(struct packets *) malloc(sizeof (struct packets))
//shared `i` and signal sending thread to send packet
...
}
// Now I need to free `(pkts+i)` like
while (i < 10)
free((pkts + i)); //Not working
//OR
free(pkts[i]); / Not working either -- in both cases error zsh: abort
Question is if I choose to free specific element at time then what is the right way plus what I need if I choose to free all elements at once

You need to use pkts as an array of pointers to struct packets.
struct packets **pkts = malloc(N * sizeof *pkts);
...
for (int i = 0; i < N; ++i) {
// setting i-th element
pkts[i]=malloc(sizeof pkts[i]);
// accessing i-th element
pkts[i]-> ...
}
for (int i = 0; i < N; ++i) {
// freeing individual element
free(pkts[i]);
pkts[i] = NULL; // avoid accidental accessing or re-freeing
}
// freeing whole array of pointers
free(pkts);
As mentioned in the comments, you probably do not need to allocate each packets individually. Just allocate an array of packets.
struct packets *pkts = malloc(N * sizeof *pkts);
...
free(pkts);
If you use C99-compliant compiler and you have a reasonable bound on the number of packets use VLA.
struct packets pkts[N]; // that's all

Related

Int value inside array cell somehow being stored as a separate 2d array address

I've created this struct, and a function that initializes all of the fields within that struct and returns a struct pointer. Within this struct I have one single dimensional array of integers, and a two dimensional array of pointers. However, when initialing and incrementing the value inside the cells inside party->fragment_sizes[I] (single dimensional array), party->fragment_sizes[] also begins to increment (two dimensional array). Party->fragment_sizes[i] goes from NULL (0x0) to (0x10000), (0x2000000) I have no idea how, but it's messing me up pretty badly. I need party_fragments_sizes to remain NULL until allocated (inside another function).
#include <stdio.h>
#include <stdlib.h>
typedef struct LonelyPartyArray
{
int **fragments; // the address of fragments[i] is being set as
int *fragment_sizes; // the value inside fragment_sizes[i]
} LonelyPartyArray;
LonelyPartyArray *createParty(int num_fragments)
{
int i;
// Allocating LonelyPartyArray struct pointer
LonelyPartyArray *party = malloc(sizeof(LonelyPartyArray));
// I am allocating these separately,
// is something going on with how my system is
// allocating space for these arrays?
// Allocating LonelyPartyArray
party->fragments = malloc(sizeof(int *) * num_fragments);
// Allocating LonelyPartyArray fragment size
party->fragment_sizes = malloc(sizeof(int) * num_fragments);
// Initializing party->fragments to NULL (not used) and fragment_sizes to zero
for (i = 0; i < num_fragments; i++)
party->fragments[i] = NULL;
for (i = 0; i < num_fragments; i++)
party->fragment_sizes[i] = 0;
// Party->fragments[I] is not remaining NULL, but is being
// incremented. (I.e., party-fragments[I] increments 0x0,
// 0x10000, 0x20000, 0x30000 etc). This needs to remain NULL.
for (i = 0; i < num_fragments; i++)
{
if (party->fragments[i] != party->fragment_sizes[i])
break;
printf("Why is this happening???? [%d]\n", i);
printf("%p\n, party->fragments[i]);
}
return NULL;
}
int main(void)
{
LonelyPartyArray *party = createParty(3);
return 0;
}
I have no idea how party->fragments[] is being set as the address for party->fragment_sizes[], but I need them to be separate.

How do i optimize the size of socket message i am sending , without missing any data?

My question is like this
below is the structure which i have to populate and send it through socket
struct Mystruct
{
int numofarray1elements;
array1[50];
int numofarray2elements;
array2[25];
};
Here size of 1 array1 member is 1024 bytes i.e total size of array1 = 50*1024 = 51200 bytes
size of 1 member of array2 is say 500 so total size of array2 = 12500 bytes
whenever i use send api of socket(unix domain socket) i have to send 51200+12500 +4+4 = 63708 bytes
Problem is i have to send entire size of structure even if i have very less
numofarray1elements, and numofarray2elements
this leads to performance issue
where in almost cases my original data can be less than 10kb but i end up sending 63k everytime
i cannot keep dynamic arrays as its socket message
i have already otimized my data strutures , array1 must have max 50 elements
array2 must have max 25 elements.
now is there any way that i can send exact data which i have populated?
please provide some method if any
Thanks
Actually the way for doing it is to have messages of variable length. One of the methods is to use a single array with undefined size as the last element of the struct. Depending on the types of the messages it could be represented by messages or by bytes, e.g.
struct Mystruct
{
int numofarray1elements;
int numofarray2elements;
char array[];
};
The size of your struct can be calculated as the size of static fields plus sizes needed for actual payload as this:
int packetSize = (sizeof(struct Mystruct) + n1 * sizeof(el1) + n2 * sizeof(el2));
now you can use it to allocate the struct and send the packet in a single operation.
struct Mystruct *packet = malloc(packetSize);
// assign packet fields
...
write(fd, packet, packetSize);
Here is a simple example which emulates a version of write/read. It will work if writer and reader have the same endian order. It also assumes that the packet size is sent separately an is known to the reader.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
struct Mystruct {
int numofarray1elements;
int numofarray2elements;
char payload[];
};
struct Element1 {
int len;
char name[30];
};
struct Element2 {
char name[20];
int len;
};
// reader emulation
void readData(int packetSize, char *dataIn) {
union {
char data[packetSize];
struct Mystruct packet;
} dataUnion;
int i;
struct Element1 *e1 = NULL;
struct Element2 *e2 = NULL;
memcpy(dataUnion.data, dataIn, packetSize);
printf("Read data e1 size is %d, e2 size is %d\n",
dataUnion.packet.numofarray1elements, dataUnion.packet.numofarray2elements);
e1 = malloc(sizeof(struct Element1) * dataUnion.packet.numofarray1elements);
e2 = malloc(sizeof(struct Element2) * dataUnion.packet.numofarray2elements);
memcpy(e1, dataUnion.packet.payload, sizeof(struct Element1) * dataUnion.packet.numofarray1elements);
memcpy(e2, dataUnion.packet.payload + sizeof(struct Element1) * dataUnion.packet.numofarray1elements,
sizeof(struct Element2) * dataUnion.packet.numofarray2elements);
for (i = 0; i < dataUnion.packet.numofarray1elements; i++) {
printf("e1[%d].len = %d, name = %s\n", i, e1[i].len, e1[i].name);
}
for (i = 0; i < dataUnion.packet.numofarray2elements; i++) {
printf("e2[%d].len = %d, name = %s\n", i, e2[i].len, e2[i].name);
}
}
void main() {
struct Element1 e1[4];
struct Element2 e2[8];
int i;
int packetSize;
struct Mystruct *packet = NULL;
for (i = 0; i < 4; i++) {
sprintf(e1[i].name, "e1:%d", i);
e1[i].len = i;
}
for (i = 0; i < 8; i++) {
sprintf(e2[i].name, "e2:%d", i);
e2[i].len = i;
}
// emulated write data
packetSize = (sizeof(struct Mystruct) + sizeof(e1) + sizeof(e2));
packet = malloc(packetSize);
packet->numofarray1elements = 4;
packet->numofarray2elements = 8;
memcpy(packet->payload, &e1, sizeof(e1));
memcpy(packet->payload + sizeof e1, &e2, sizeof(e2));
// here you do write data, e.g. write(socFd, packet, packetSize);
// emulate read data
readData(packetSize, (char*)packet);
}
Instead of using structures, use TLV mechanism. So for your solution: you can use Type , , Count of Type, Length , Value.
Define types which is known at both receiver and sender side
Define your message structure as
Type taking 2 bytes, Count-of-type taking 2 or 4 bytes , Length taking 4 bytes and Value.
This is extensible as you can add any number of types in future as long as the type is known at both side. At receiver side if type is not known, they can ignore that TLV.
You should not send structs over network protocols (or store them in files, etc). You need to serialize them.
But to solve your problem, simply change your send code:
//this is what your code looks like, I assume:
write(sockFd, myStructVariable, sizeof(struct MyStruct));
to:
//be aware of writev(2) if you want to send these in one system call at once, or copy them into one buffer
write(sockFd, myStructVariable.numofarray1elements, sizeof(int));
write(sockFd, myStructVariable.array1, sizeof(MyArray1) * myStructVariable.numofarray1elements);
write(sockFd, myStructVariable.numofarray2elements, sizeof(int));
write(sockFd, myStructVariable.array2, sizeof(MyArray2) * myStructVariable.numofarray2elements);
or something similar
Then change your receive code:
read(sockFd, myStructVariable.numofarray1elements, sizeof(int));
read(sockFd, myStructVariable.array1, sizeof(MyArray1) * myStructVariable.numofarray1elements);
read(sockFd, myStructVariable.numofarray2elements, sizeof(int));
read(sockFd, myStructVariable.array2, sizeof(MyArray2) * myStructVariable.numofarray2elements);
of course, you could also leave the array and counts defined locally and send those instead. Make sure you check for errors, short reads, etc
Take a look at flatbuffers as well, this lets you write structures that come with serialization functions

error when using realloc function

I have a program to dynamically increase the capacity of a hashtable when the size of any
of its buckets goes beyond a maximum value. However i am being hit with a "* glibc
detected * realloc(): " error when i try to run my code.
Could anyone help me out with it? Sorry for positing so much code here,but i really need
the help.
/* structure for the hashtable containing an array of nodes */
typedef struct Hashtable hashtable;
struct Hashtable {
struct node **list;
};
/* the function which resizes the hashtable and re-arranges the values according to
new capacity */
void reSize(hashtable *h)
{
int i;
node **newlist=realloc(h->list,2*capacity*sizeof(node*));
h->list=newlist;
int temp=capacity,index;
capacity=capacity * 2;
for(i=temp;i<capacity;i++)
h->list[i]=calloc(1,sizeof(node));
}
/* mystructure init */
struct hashtable *mystruct_init()
{
int i;
hashtable *hashtable =calloc(1, sizeof(*hashtable));
// loop through and allocate memory for each element in list
hashtable->list= calloc(1,sizeof(node *));
for (i = 0; i < 16; i++) {
hashtable->list[i] = calloc(1, sizeof(node));
}
return hashtable;
}
/* in my main function */
hashtable *h1=(hashtable *) mystruct_init();
hashtable *h2=(hashtable *) mystruct_init();
I am getting this "* glibc detected * ./compareDocs: realloc(): " error when i try
to run it. Could someone point out as to where i am going wrong in my code?? I've spend
a whole night trying to debug this thing, so any help would be really nice. Sorry for
posting so many lines of code..
What happens is that you allocate an array of length capacity. You then double capacity on the line that reads capacity=capacity * 2. And then you write of the end of the array in the for loop because the array is only half as long as you think it is.
node **newlist=realloc(h->list,capacity*sizeof(node*));//array of length capacity
h->list=newlist;
....
capacity=capacity * 2;//oops, capacity is now twice as big as the array
for(i=temp;i<capacity;i++)
h->list[i]=calloc(1,sizeof(node));//and now we are writing off the end
}
There are quite likely other errors in your code. I can't see how the capacity variable is handled. Is it a global? Where is it initialised?
Also, the code you added in your edit is clearly wrong.
hashtable->list= calloc(1,sizeof(node *));
for (i = 0; i < 16; i++) {
hashtable->list[i] = calloc(1, sizeof(node));
}
Here you appear to set the initial capacity of the list to 1, but then assign 16 values. Clearly the calloc should be passed 16 rather than 1.
In your mystruct_init() function you've allocated only one node * for your your list:
hashtable->list= calloc(1,sizeof(node *));
And then went on to dereference elements past the end of the allocated memory:
for (i = 0; i < 16; i++) {
hashtable->list[i] = calloc(1, sizeof(node));
Also, in your reSize() function you use the variable capacity but that does not appear to be defined anywhere. Is this your real code? And if it is, what is the value of capacity?
Edit: You should probably make the code in your init function look like this:
struct hashtable *mystruct_init()
{
int i;
hashtable *hashtable =calloc(1, sizeof(*hashtable));
// loop through and allocate memory for each element in list
hashtable->list= calloc(capacity, sizeof(node *));
for (i = 0; i < capacity; i++) {
hashtable->list[i] = calloc(1, sizeof(node));
}
return hashtable;
}
Notice that I've used capacity in the call to calloc() and as the controlling value in the following for loop.

How to allocate an array of pointers to a struct

I am using the CvPoint2D32f struct of opencv, which is defined as
typedef struct CvPoint2D32f
{
float x; /* x-coordinate, usually zero-based */
float y; /* y-coordinate, usually zero-based */
}
CvPoint2D32f;
I am trying to allocate an array of pointers of these objects as follows, and it is not working. How is this to be accomplished?
CvPoint2D32f *cvpoints[8];
for (i = 0; i < 16; i++)
{
if (i % 2 == 0)
{
(*cvpoints)[i/2].x = float(points[i]); // points is an array of ints.
}
else
{
(*cvpoints)[i/2].y = float(points[i]);
}
}
You have an array of pointers to CvPoint2D32f, not an array of the structs themselves. You have no memory allocated for the actual structures. You have three options:
Change your declaration to CvPoint2D32f cvpoints[8]; so you have all of the structures in an array on the stack.
After you allocate the array for the pointers, add a malloc statement to allocate memory. Example:
CvPoint2D32f *cvpoints[8];
for (i = 0; i < 8; i++)
{
cvpoints[i] = (CvPoint2D32f *)malloc(sizeof(CvPoint2D32f));
}
Use malloc to allocate size for all the structures. Example:
CvPoint2D32f *cvpoints = (CvPoint2D32f *)malloc( 8 * sizeof(CvPoint2D32f));
CvPoint2D32f *cvpoints = (CvPoint2D32f*) malloc(sizeof(struct CvPoint2D32f) * 8);
memset(cvpoints, \0, sizeof(struct CvPoint2D32f) * 8);
for (i = 0; i < 16; i++)
{
if (i % 2 == 0)
{
cvpoints[i/2].x = float(points[i]); // points is an array of ints.
}
else
{
cvpoints[i/2].y = float(points[i]);
}
}
And when you're done with them, you free the memory:
free(cvpoints);
Where do these pointers point to? I guess what you want to do is allocate dynamic memory for the structs, but I don't see any memory allocation in your code. Currently all pointers point to undefined memory, so of course this will fail.
You are just creating the pointers, but you need them to point to something in memory!
Example:
struct CvPoint2D32f *cvpoint = (struct CvPoint2D32f *)malloc(sizeof(struct CvPoint2D32f));
if (cvpoint == NULL) {
//malloc error
}

Difference in uses between malloc and calloc

gcc 4.5.1 c89
I have written this source code for my better understanding of malloc and calloc.
I understand, but just have a few questions.
dev = malloc(number * sizeof *devices);
is equal to this calloc. I am not concerned about clearing the memory.
dev = calloc(number, sizeof *devices);
What is that exactly, compared to doing this 5 times in a while loop:
dev = malloc(sizeof *devices);
I guess the first one and the second is creating a pointer to 5 struct device. And the third is creating a single pointer to a struct device?
My program illustrates this 3 different methods compiled and ran with valgrind --leak-check=full.
Many thanks for any advice.
#include <stdio.h>
#include <stdlib.h>
struct Devices {
#define MAX_NAME_SIZE 80
size_t id;
char name[MAX_NAME_SIZE];
};
struct Devices* create_device(struct Devices *dev);
void destroy_device(struct Devices *dev);
int main(void)
{
size_t num_devices = 5;
size_t i = 0;
struct Devices *device = NULL;
struct Devices *dev_malloc = NULL;
struct Devices *dev_calloc = NULL;
for(i = 0; i < num_devices; i++) {
device = create_device(device);
/* Assign values */
device->id = i + 1;
sprintf(device->name, "Device%zu", device->id);
/* Print values */
printf("ID ----- [ %zu ]\n", device->id);
printf("Name --- [ %s ]\n", device->name);
/* Test free */
destroy_device(device);
}
printf("\n");
dev_malloc = malloc(num_devices * sizeof *dev_malloc);
for(i = 0; i < num_devices; i++) {
/* Assign values */
dev_malloc->id = i + 1;
sprintf(dev_malloc->name, "dev_malloc%zu", dev_malloc->id);
/* Print values */
printf("ID ----- [ %zu ]\n", dev_malloc->id);
printf("Name --- [ %s ]\n", dev_malloc->name);
}
/* Test free */
destroy_device(dev_malloc);
printf("\n");
dev_calloc = calloc(num_devices, sizeof *dev_calloc);
for(i = 0; i < num_devices; i++) {
/* Assign values */
dev_calloc->id = i + 1;
sprintf(dev_calloc->name, "dev_calloc%zu", dev_calloc->id);
/* Print values */
printf("ID ----- [ %zu ]\n", dev_calloc->id);
printf("Name --- [ %s ]\n", dev_calloc->name);
}
/* Test free */
destroy_device(dev_calloc);
return 0;
}
struct Devices* create_device(struct Devices *dev)
{
/* Not checking for memory error - just simple test */
return dev = malloc(sizeof *dev);
}
void destroy_device(struct Devices *dev)
{
if(dev != NULL) {
free(dev);
}
}
calloc(a,b) and malloc(a*b) are equivalent except for the possibility of arithmetic overflow or type issues, and the fact that calloc ensures the memory is zero-byte-filled. Either allocated memory that can be used for an array of a elements each of size b (or vice versa). On the other hand, calling malloc(b) a times will results in a individual objects of size b which can be freed independently and which are not in an array (though you could store their addresses in an array of pointers).
Hope this helps.
malloc(n) allocates n bytes plus padding and overhead.
calloc(m, n) allocates m*n bytes plus padding and overhead, and then zero's the memory.
That's it.
edited for clarity
I guess the first one and the second is creating a pointer to 5 struct device. And the third is creating a single pointer to a struct device?
The first one malloc(number * sizeof(*devices)) would allocate enough memory to store number of Devices. As others have mentioned, you can treat this block like an array of Device. The pointer you get back will point to the beginning of the block.
int number = 5;
Device *ptr = malloc(number * sizeof(*ptr));
/* stuff */
free(ptr);
The second one that uses calloc does the same thing, while also initializing the memory to 0. Again, you can use treat the block like an array of Device.
int number = 5;
Device *ptr = calloc(number, sizeof(*ptr));
/* stuff */
free(ptr);
The third one, looping 5 times, would result in 5 different pointers to 5 different blocks large enough to store one Device each. This also means each of the 5 pointers has to be free'ed individually.
Device *ptrs[5];
for(int i = 0; i < 5; ++i)
{
ptrs[i] = malloc(sizeof(*ptrs[i]));
}
/* stuff */
for(int i = 0; i < 5; ++i)
{
free(ptrs[i]);
}
The first two create an array of 5 devices in contiguous memory. The last malloc, done five times, will create 5 individual devices which are not guaranteed to be in contiguous memory.
All three loops in your program use only one struct Devices object at a time. The later ones allocate extra memory as though they are going to use multiple objects, but then keep overwriting the beginning of that memory. If you tried to use the object with ID 1 after setting up the object with ID 2, you would find there is no longer any object with ID 1.
Instead, you could do something like this to treat the allocated memory as an array of structs:
dev_malloc = malloc(num_devices * sizeof *dev_malloc);
for (i=0; i<num_devices; i++) {
/* Assign values */
dev_malloc[i].id = i + 1;
sprintf(dev_malloc[i].name, "dev_malloc%zu", dev_malloc[i].id);
/* Print values */
printf("ID ----- [ %zu ]\n", dev_malloc[i].id);
printf("Name --- [ %s ]\n", dev_malloc[i].name);
}
free(dev_malloc);
Look at an implementation of calloc to see the differences. It's probably something like this:
// SIZE_MAX is defined in stdint.h from C99
void *calloc( size_t N, size_t S)
{
void *ret;
size_t NBYTES;
// check for overflow of size_t type
if (N > SIZE_MAX / S) return NULL;
NBYTES = N * S;
ret = malloc( NBYTES);
if (ret != NULL)
{
memset( ret, 0, NBYTES);
}
return ret;
}
As you point out, calloc zeroes out the memory is allocates, while malloc doesn't.
Your examples 1 & 2 each allocate a single contiguous block of five structs (and returns a pointer to that block), whereas example 3 allocates five separate blocks of one struct each (and gives you five pointers unrelated to one another.)

Resources