Transferring variables using structure - c

I want to transfer few variables using structure. Following is the sample program code. When I run this program, I get segmentation fault. I use gcc compiler.
Can anyone help me with this?
struct data{
const char * ip;
const char * address;
const char * name;
};
int fun(struct data *arg) {
//struct data *all;
const char *name = arg->name;
printf("\n My name is:%s",name);
return 1;
}
int main(int argc, char * const argv[]) {
struct data * all;
int k=0;
//data.name = argv[1];
all->name=argv[1];
k = fun(all);
printf("\n k is:%d ",k);
return 0;
}

The problem is here:
struct data * all;
all->name=argv[1];
You have not allocated memory for all. When you have an uninitialized pointer, it is pointing to random locations in the memory, which you probably won't have access to. You have two options:
Allocate on the stack:
struct data all;
all.name=argv[1];
k = fun(&all);
Allocate on the heap:
struct data *all = malloc(sizeof(*all));
if (all != NULL)
{
all->name=argv[1];
k = fun(all);
}
free(all);
The first case is good when you know that all will be needed only in the current function (and those you call). Therefore, allocating it on the stack is sufficient.
The second case is good for when you need all outside the function creating it, for example when you are returning it. Imagine a function initializing all and return it for others to use. In such a case, you can't allocate it on the stack, since it will get destroyed after the function returns.
You can read more about it in this question.

You need to allocate memory and assign it to the pointer all:
struct data * all;
int k=0;
all = malloc(struct data);
all->name=argv[1];
k = fun(all);
//...
free(all);
or use a local struct and pass its pointer to the function:
struct data all;
int k=0;
all.name=argv[1];
k = fun(&all);

all is a pointer to type struct data. You never assigned it, so it doesn't point to anything.
You need to do one of the following:
allocate all on the stack:
struct data all;
allocate all on the heap:
struct data* all = malloc(sizeof (struct data));
// don't forget to check if the allocation succeeded,
//and don't forget to free it when you're done

Related

Passing a struct to void* param then copying it to a void*, reconstructing gives garbage value

I am really confused with passing my struct to void pointers, I'm not sure which one can be assigned directly and which one should be memcpyed, I've tried a lot of combinations but it does not seem to work. Any help would be very appreciated!
This is my C code
struct SomeStruct {
int a;
char name[10];
};
void *randoms[10];
void transferFunction(void* data, int index) {
// This function copies data to randoms[index]
// I would like to have the whole struct's data in randoms[index]
memcpy(&randoms[index], data, sizeof(struct SomeStruct));
}
struct SomeStruct *ss = malloc(sizeof(struct SomeStruct));
ss->a = 1;
strcpy(ss->name, "abc");
transferFunction(ss, 0);
My goal is to have the randoms[index] having the struct's data as another function is going to read from it, as shown below, but I am unable to retrieve the struct data correctly, it gives me some garbage value
void readFunction() {
struct *SomeStruct ss = malloc(sizeof(struct SomeStruct));
memcpy(ss, &randoms[index], sizeof(struct SomeStruct));
printf(ss->name);
}
Does anyone knows how to solve this problem? Thank you very much!!!
You can not "copy in to a void".
A void * can contain a memory address, but does not contain any information about the size of the data at that address.
Also, it can not contain any data, only an address!
In this line:
void *randoms[10];
You create an array that can hold 10 addresses.
You never initialize this array, so it will start out all zeroes (this only works for global variables in C).
You can put the address of your structure in to the array, like so:
random[0] = (void*)ss;
However, this does not transfer any data, so if you free the original structure (ss) your data is gone, and the address in random[0] is illegal.
If you want to transfer data you need to create array of struct SomeStruct or you need to allocate another SomeStruct, store its address in random[0] then memcpy to that address.
void transferFunction(void* data, int size, int index)
{
randoms[index] = malloc(size);
if (randoms[index] != NULL) {
memcpy(randoms[index], data, size);
}
}
Your code has some problems:
struct *SomeStruct ss = ... should be struct SomeStruct *ss =.
You are not cheking the return value of malloc() (which may fail).
You are not freeing ss allocated with malloc(). You should call free() on ss.
My goal is to have the randoms[index] having the struct's data
Lev M.'s answer already answers this part.
as another function is going to read from it
Simply assign your void pointer to a SomeStruct pointer:
void readFunction(int index)
{
if (index >= 10) // Index out of range
return;
struct SomeStruct *ss = randoms[index];
printf("%s\n", ss->name);
}

Can I iterate dynamic array without knowing the size of it

I allocated some data in a dynamic array of a struct. Can I iterate that struct * without knowing it's size somehow?
Would this work?
int main() {
struct *foo = NULL;
//struct filling
iterate_foo(foo);
}
void iterate_foo(struct *foo) {
int i=0;
while (foo[i] != NULL) { // Would this work?
//something
}
}
The only way that can work is if you have a sentinel value in the array that indicates the end. Strings in C work that way.
For instance, if you invoke strcpy(a, b), then characters from b will be copied to a until and including the value zero. If there's no zero terminator within the b array, or if a is not big enough to hold all the characters, the function call leads to undefined behavior.
If you don't want to use a sentinel value, you have the option of passing the size as a separate parameter. Another way is to wrap things in a container struct, like this:
struct container {
struct mystruct *data;
size_t size;
}
Furthermore, struct *foo = NULL; is wrong. It has to be something like struct mystruct *foo = NULL;
But if you have this code:
void foo(T *ptr) {
// Do something
}
int main(void) {
T *a = malloc(N * sizeof *a);
T b[N];
foo(a);
foo(b);
}
Then it's completely impossible for foo to figure out N in a portable way. In some cases, believe that the implementation of malloc stores the size right before the data. But don't try to exploit that. It will only cause severe head ache.

Initialize an empty nested struct using a function

I have to initialize tCoworking coworking by implementing init_coworking function that is declared at the end.
/* Constants *********************************************************/
#define nWorkSpaces 50
#define unlimited 2000
/* Types *************************************************************/
typedef enum {tableFlex, tableFix, officeFix} rate;
typedef char string[55];
typedef struct {
int reservationId;
float monthPayment;
} tContractAnnex;
typedef struct {
int id;
string name;
int discount;
} tPartner;
typedef struct {
int id;
float surface;
rate rateType;
} tWorkspace;
typedef struct {
int partnerId;
int month;
int year;
tContractAnnex annex;
} tContract;
typedef struct {
tWorkspace workSpace[nWorkSpaces];
tContract contract[unlimited];
tPartner partner[unlimited];
} tCoworking;
/* Function declaration */
void init_coworking(tCoworking *coworking);
As you can see the problem I have is that tCoworking is a nested struct with array of stucts as data types..
So far I'm doing this in order to initialize it but it must be a better way to do it.
void init_coworking(tCoworking *coworking){
coworking = malloc(sizeof(tCoworking));
coworking->partner[0].id = 0;
coworking->partner[0].discount = 0;
strcpy(coworking->partner[0].name, "");
coworking->workSpace[0].id = 0;
coworking->workSpace[0].rateType = 0;
coworking->workSpace[0].surface = 0;
coworking->contract[0].partnerId = 0;
coworking->contract[0].year = 0;
coworking->contract[0].month = 0;
coworking->contract[0].annex.monthPayment = 0;
coworking->contract[0].annex.reservationId = 0;
}
void init_coworking(tCoworking *coworking) {
coworking && memset( coworking, 0, sizeof( tCoworking ) );
}
memset initializes a block of memory - of specifiable length - to a single byte value. Your example indicates that you desire zero-initialization of the entire object, so memset serves this purpose well.
NULL-check your input argument.
I recommend you not malloc or calloc in your function because your function signature implies that the caller is the owner of the tCoworking. If you malloc within your init_coworking() function, then you'll have created a new heap-allocated instance of a tCoworking with no clear ownership. You can try keep track of newly-allocated objects in some type of container, but that's going far beyond the scope of your question -- keep it simple.
The simplest way is to use calloc. Like malloc it allocates memory for you but it also sets all the memory to zero.
However - more important is that your current function doesn't make sense. The memory you allocate is simply lost. The caller of init_coworking will never get the allocated and initialized memory.
Either you should:
Not do any malloc(or calloc)
or
Return the malloced pointer.
Since the prototype suggest that you get a tCoworking pointer, the most likely thing is that it's already allocated (in some way), i.e. you want option 1.
So just do:
void init_coworking(tCoworking *coworking){ // NO malloc
memset(coworking, 0, sizeof(tCoworking));
}
In case you only want the first array member set to zero (like your code indicates) you may get a little performance improvement by:
void init_coworking(tCoworking *coworking){ // NO malloc
memset(&coworking->partner[0], 0, sizeof(coworking->partner[0]));
... similar for the other arrays ...
}
but I doubt that's worth the trouble...

How to fix allocated memory from a struct hack in a different method?

I'm developing a driver in C for communication and the messages exchanged don't have a fixed size. The recommendation of communication bus is to use structs for multi-topics, which is also my case.
My 1st problem: I have to keep listening for new messages, and when I get one I have to process message data (it has a delay) and still listening for new messages.
1st solution: using thread when got new messages to process data.
My 2nd problem: Data in message can have multiple data of a struct, and my communicator requires using a struct to organize this multiple values.
2nd solution: using struct hack to allocate memory dynamic size of struct.
My current problem: when I'd pass my struct as argument to the thread, or any function, I'm loosing data structure and getting wrong values.
A short test which a made is:
typedef struct test{
int size;
int value[];
} test;
void allocation(test *v){
test *aux = (test *)malloc(sizeof(test)+3*sizeof(int));
int i;
aux->value[0] = 2;
aux->size = 3;
aux->value[1] = 1;
aux->value[2] = 5;
printf("Teste1 %d\n",aux->size);
for(i=0; i < aux->size; i++){
printf("%d\n", aux->value[i]);
}
*v = *aux;
}
void cleanup(test *v){
free(v);
}
int main(int argc, char *argv[]){
test v;
int i;
allocation(&v);
printf("Teste2 %d\n",v.size);
for(i=0; i < v.size; i++){
printf("%d\n", v.value[i]);
}
//cleanup(&v);
return 0;
}
In this test I got right values in first print and wrong values in second (only v.size is giving a right value).
And my struct is a little more complex than that in test. My struct is like:
typedef struct test1{
double v1;
double v2;
} test1;
typedef struct test2{
int size;
test1 values[];
} test2;
Do you know how to fix my memory struct in that function, once I have all elements necessary to fix? Please, keep in mind that is desirable (not required) that I could also allocate multiple test2 data.
The thing here is that you assign structs with incomplete member int value[]; Though it is in principle OK to copy two structs by value (and this is actually what happens if you write *v = *aux); However, as the compiler does not know which size member value[] will take on at runtime, the "sizeof" of v as well as the size of *aux is always 4, i.e. the known size of the one int member size. Hence, only this is copied, whereas the value[]-array simply gets not copied.
A way out out this situation would be require a pointer to a pointer (i.e. allocation(test **v), such that the memory reserved can be directly assigned to it, using a pointer to struct test in main, i.e. test *vptr, and call allocation(&vptr).
If you cannot avoid passing a reverence to the value (instead of a reference to a pointer to the value), I suppose you'll have to use memcpy to transfer the contents. But this does actually not make sense, because then the receiver must provide enough space to take on the value[]-array in advance (which is not the case if you simple declare a variable of the form test v). An then the malloc and the aux would make no sense; you could directly write into object v passed by reference.
You are declaring v as non-pointer, meaning that the memory is already allocated for v when you declare it in main. Sending the reference to your allocation only copies the size correctly since it is not dynamically allocated. Correct way to do this would be to:
Declare your v as pointer
Make your allocation return test* (test* allocation())
Assign it to v in main. i.e. something like v = allocate()
And use v like a pointer from then on
EDIT: Since OP wants this to work only as arguments, best way to go about it is using double pointer. Check the following code:
typedef struct test{
int size;
int value[];
} test;
void allocation(test **v){
test *aux = (test *)malloc(sizeof(test)+3*sizeof(int));
int i;
aux->value[0] = 2;
aux->size = 3;
aux->value[1] = 1;
aux->value[2] = 5;
printf("Teste1 %d\n",aux->size);
for(i=0; i < aux->size; i++){
printf("%d\n", aux->value[i]);
}
*v = aux;
}
void cleanup(test *v){
free(v);
}
int main(int argc, char *argv[]){
test **v;
v = malloc (sizeof (test*));
int i;
allocation(v);
printf("Teste2 %d\n",(*v)->size);
for(i=0; i < (*v)->size; i++){
printf("%d\n", (*v)->value[i]);
}
//cleanup(&v);
return 0;
}
Please note that your cleanup will change too after this.

ANSI C Memory allocation for pointer to struct throws non-fatal run-time error

I am using ANSI C code, generated from a code generator that produces several layers of nested struct as well as function prototypes with argument lists that use pointers to the top layer struct for passing or accessing data located in the inner mmost struct.
Because the function prototypes pass pointers to struct, the application must allocate memory to access or write data to the inner most struct members. I am seeing the problem when attempting to allocate memory for the pointer to the second nested struct.
The actual error message I get is a non-fatal, run-time:
"Not enough space for casting expression to 'pointer to struct data'."
I am not explicitly casting anything, so I suspect the implementation of malloc() may have an assert that generates the message when it sees some condition. The wording of this error may be specific to my environment (I am using LabWindows/CVI) but I would be interested in hearing of results of other ANSI C compilers as well.
Here is a simplified, complete, code snippet that should compile, build and run (up to the error location, which is commented in-line)
I would appreciate comments on the cause of my error, and suggestions on how to fix it.
#include <ansi_c.h> //specific to LabWindows/CVI - change as needed for your environment
struct request
{
struct data *pData;
};
struct data
{
char *wsDate;
char *wsDuration;
char *wsFailures;
int __sizeM_Details;
struct details *M_Details;
};
struct details
{
char *wsStep;
char *wsTestDesc;
char *wsLowLim;
};
typedef struct request REQUEST; // from mtdf function prototype request argument (4)
typedef struct details DETAILS; // member of REQUEST - _ns1__MTDFData_MTDFDetail
void allocate(REQUEST *a, int numRecords);
void freemem(REQUEST *c, int numRecords);
int main(void)
{
REQUEST b, *pB;
pB = &b;
allocate(pB, 10);
freemem(pB, 10);
return 0;
}
void allocate(REQUEST *c, int numRecords)
{
DETAILS m_Param;
REQUEST b;
struct data d;
size_t size_c = sizeof(c);
c = malloc(size_c); //4 bytes
size_t size_c_data = sizeof(c->pData);
c->pData = malloc(size_c_data); //Breaks here - this is just a pointer,
//should it not just allocate 4 bytes
//and continue?
// Actual error message:
// "Not enough space for casting expression to 'pointer to struct data'."
c->pData->wsDate = calloc(80, sizeof(char));
c->pData->__sizeM_Details = numRecords;
c->pData->M_Details = calloc((numRecords + 1) , sizeof(m_Param));
}
void freemem(REQUEST *c, int numRecords)
{
free(c->pData->M_Details);
free(c->pData->wsDate);
free(c->pData);
free(c);
}
There's several fundamental problems, here:
In allocate(), all that memory you're malloc()ing is being lost at the end of your function, because you're assigning it to a local variable, c, which gets destroyed at the end of your function. You never use the address of the struct with automatic storage duration that you pass into the function. If you're passing the address of an object with automatic storage duration, then you should malloc() memory for the members, but not for the struct itself, since it obviously already has memory.
Then, in freemem(), you attempt to free() the memory associated with b, which is a struct with automatic storage duration. You can only free() memory that you've dynamically allocated.
You have a curious comment in allocate(), "this is just a pointer, should it not just allocate 4 bytes and continue?". If you're on a system with 32 bit pointers, then that is indeed what you allocated, but c->pData is a pointer to struct data which looks like it needs 28 bytes on a 32 bit machine, so you should be allocating a lot more than 4 bytes for it. Lines like c->pData->wsDate = ... seem to indicate that you're well aware it's a pointer to a struct data, so it's really unclear why you think you should only be allocating 4 bytes. When you allocate memory for an ANYTHING * to point to, then you need to allocate enough memory for an ANYTHING, not for an ANYTHING *, i.e. enough memory for the thing it's going to point to. The fact that you're trying to assign the memory to your pointer in the first place proves that you already have the memory for your pointer, otherwise you wouldn't be able to do that (providing that you haven't messed up some previous allocation, of course).
You never check the return from malloc() and calloc(), and you should.
Names beginning with a double underscore are always reserved for the implementation, so you should call __sizeM_Details something else.
sizeof(char) is 1 by definition, so there's never any need to use it.
It's unclear why you're allocating memory for numRecords + 1 of your struct details, rather than just numRecords as would seem intuitive. Perhaps you're looking to set that last one to NULL as a sentinel value, but if you're already storing the number of records in your struct, then this isn't really necessary.
Here's what your code ought to look like:
#include <stdio.h>
#include <stdlib.h>
struct request {
struct data * pData;
};
struct data {
char * wsDate;
char * wsDuration;
char * wsFailures;
int sizeM_Details;
struct details * M_Details;
};
struct details {
char * wsStep;
char * wsTestDesc;
char * wsLowLim;
};
typedef struct request REQUEST;
typedef struct details DETAILS;
void allocate(REQUEST * c, const int numRecords);
void freemem(REQUEST * c);
int main(void)
{
REQUEST b;
allocate(&b, 10);
freemem(&b);
return 0;
}
void allocate(REQUEST * c, const int numRecords)
{
if ( !(c->pData = malloc(sizeof *c->pData)) ) {
perror("couldn't allocate memory for c->pData");
exit(EXIT_FAILURE);
}
if ( !(c->pData->wsDate = calloc(80, 1)) ) {
perror("couldn't allocate memory for c->pData->wsDate");
exit(EXIT_FAILURE);
}
if ( !(c->pData->M_Details = calloc(numRecords + 1,
sizeof(*c->pData->M_Details))) ) {
perror("couldn't allocate memory for c->pData->M_Details");
exit(EXIT_FAILURE);
}
c->pData->sizeM_Details = numRecords;
}
void freemem(REQUEST * c)
{
free(c->pData->M_Details);
free(c->pData->wsDate);
free(c->pData);
}
If allocating automatic storage for b was a mistake, and you really do want to dynamically allocate everything, including your struct request, then it should look like this:
#include <stdio.h>
#include <stdlib.h>
struct request {
struct data * pData;
};
struct data {
char * wsDate;
char * wsDuration;
char * wsFailures;
int sizeM_Details;
struct details * M_Details;
};
struct details {
char * wsStep;
char * wsTestDesc;
char * wsLowLim;
};
typedef struct request REQUEST;
typedef struct details DETAILS;
REQUEST * allocate(const int numRecords);
void freemem(REQUEST * c);
int main(void)
{
REQUEST * b = allocate(10);
freemem(b);
return 0;
}
REQUEST * allocate(const int numRecords)
{
REQUEST * c = malloc(sizeof *c);
if ( !c ) {
perror("couldn't allocate memory for c");
exit(EXIT_FAILURE);
}
if ( !(c->pData = malloc(sizeof *c->pData)) ) {
perror("couldn't allocate memory for c->pData");
exit(EXIT_FAILURE);
}
if ( !(c->pData->wsDate = calloc(80, 1)) ) {
perror("couldn't allocate memory for c->pData->wsDate");
exit(EXIT_FAILURE);
}
if ( !(c->pData->M_Details = calloc(numRecords + 1,
sizeof(*c->pData->M_Details))) ) {
perror("couldn't allocate memory for c->pData->M_Details");
exit(EXIT_FAILURE);
}
c->pData->sizeM_Details = numRecords;
return c;
}
void freemem(REQUEST * c)
{
free(c->pData->M_Details);
free(c->pData->wsDate);
free(c->pData);
free(c);
}

Resources