Segfault on copying struct - c

I have a struct as following:
extern struct team_t
{
char *name1;
char *email1;
char *name2;
char *email2;
} team;
struct team_t team =
{
"some string1",
"some string2",
"some string3",
"some string4"
};
Then in another file I create the following function that copies this struct into a new struct:
void *ucase( struct team_t *team)
{
struct team_t *ucase_team = malloc( sizeof *ucase_team);
memcpy ((char*)ucase_team, (char *)team, sizeof (ucase_team));
return NULL;
}
However, when I want to call ucase(team), I'm getting a segfault. I need to use void * because this will later be used for shell signals. What am I missing?
Update: Following call gives type argument of unary ‘*’ (have ‘struct team_t’) error:
ucase(*team)
Update 2: I have removed Null return and used ucase(team) but still getting segfault.

The last argument of memcpy() should be sizeof(struct team_t) instead of sizeof (ucase_team) as ucase_team is a struct pointer variable. It can be either sizeof(*ucase_team) or sizeof(struct team_t).
Also calling team() function like
ucase(*team);
is wrong as team is not a variable of pointer type, it's a normal structure variable. Probably you want
ucase(&team);

Related

Move a struct through (void *) function argument back to struct

I am trying to send a struct through a function, taking (void *) as a singular argument, and then signing it to a struct of the same type (as in main/before function) inside the function. This results in error every single way I attempt to do it. Anyone knows how to do this?
struct a
{
SDL_Surface *s;
};
struct b
{
SDL_Window *window;
};
struct struct_of_structs
{
struct a *struct_a;
struct b *struct_b;
};
void loop(void *arg)
{
struct_of_structs s_structs;
// how do I assign arg to s_structs?
s_structs = arg; // error
s_structs = *arg; // error
s_structs = &arg; // error
*s_structs = arg; // error
&s_structs = arg; // error
*s_structs = *arg; // error
*s_structs = &arg; // error
&s_structs = *arg; // error
&s_structs = &arg; // error
}
int main()
{
struct struct_of_structs struct_struct;
struct a a_struct;
struct b b_struct;
struct_struct.a = a_struct;
struct_struct.b = b_struct;
loop(&struct_struct);
}
Edit I have uploaded my original code at pastebin. Whatever order of pointer or casting I add to the "arg" inside the loop, I get the error:
error: expected expression
arguments = (*(loop_args*)arg);
error: use of undeclared identifier 'loop_args'
in every way I add the casting. Doing struct loop_args arguments* = ((loop_args*)arg) does not work, etc, etc. It always fails with "expected expression blah blah".
P.S. adding your solution to a random main.c using the dummy code worked and I learned something new, thanks a lot!
s_structs = (*(struct_of_structs *)arg);
should do the trick.
basically what happens is you send a pointer to a struct but the function receives it as a void pointer, so to go from a void * to a struct you can't dereference a void *, so you cast the argument to a struct_of_structs pointer, and dereference it which will result in what you are looking for.
You need to create a pointer, not a new struct.
void loop(void *arg)
{
struct_of_structs *ps_structs =0;
// how do I assign arg to s_structs?
ps_structs = (struct_of_structs *) arg; // error
}
With the help of all the answers as well as the comments, I solved it!
struct_of_structs s_structs* = (struct struct_of_structs*)arg;
I cannot simply cast it to a struct of type "struct_of_structs", need to cast it to a type that is a struct aka "struct struct_of_structs"! Thanks everyone!

Pointer to incompatible class type is not allowed (pass struct by pointer)

I have such struct
struct Request
{
char *command;
char firstSetName[SET_NAME_LENGTH];
char secondSetName[SET_NAME_LENGTH];
char resultSetName[SET_NAME_LENGTH];
int input[sizeof(int) * 4];
};
And such a method
int parseToReadRequest(char * command, struct Request * request)
{
printf("Command is : %s\n", command);
strcpy(request->firstSetName, "dddd"); <---- It this line I get an error
return 0;
}
But I get an error in line that I marked above
Pointer to incompatible class type is not allowed
What am I doing wrong?
EDIT
I have commented on this line
struct Request
{
char *command;
char firstSetName[SET_NAME_LENGTH];
char secondSetName[SET_NAME_LENGTH];
char resultSetName[SET_NAME_LENGTH];
/*int input[sizeof(int) * 4];*/ <---- This
};
And anyway I get an error on this line
int parseToReadRequest(char * command, struct Request * request)
{
printf("Command is : %s\n", command);
strcpy(request->firstSetName, "ddd"); <--- This
return 0;
}
parcer.c:7:19: error: incomplete definition of type 'struct Request'
strcpy(request->firstSetName, "ddd");
I suspect you haven't actually #included the definition header for the struct. Without the definition, C will take struct Request as an incomplete declaration, which means you can manipulate the pointer (basically pass it to children that do have the declaration or store it), but you can't access members.
This is why you generally see the typedef thing so the struct keyword is not required and the error occurs earlier.

How to solve the error: assignment to expression with array type

I am asked to create a carinfo structure and a createcarinfo() function in order to make a database. But when trying to allocate memory for the arrays of the brand and model of the car, the terminal points out two errors.
For:
newCar->brand =(char*)malloc(sizeof(char)*(strlen(brand) + 1));
newCar->model = (char*)malloc(sizeof(char)*(strlen(model) + 1));
it says that there is an error: assignment to expression with array type and an arrow pointing to the equal sign.
struct carinfo_t {
char brand[40];
char model[40];
int year;
float value;
};
struct carinfo_t *createCarinfo(char *brand, char *model, int year, float value){
struct carinfo_t *newCar;
newCar=(struct carinfo_t*)malloc( sizeof( struct carinfo_t ) );
if (newCar){
newCar->brand =(char*)malloc(sizeof(char)*(strlen(brand) + 1));
newCar->model = (char*)malloc(sizeof(char)*(strlen(model) + 1));
strcpy(newCar->brand, brand);
strcpy(newCar->model, model);
//newCar->brand=brand;
//newCar->model=model;
newCar->year=year;
newCar->value=value;
}
return newCar;
};
Two things.
In your code, brand and model are already of array type, they have memory allocated to them based on their size (char [40]) on declaration. You need not allocate any memory using the allocator function (unlike pointers, on other hand).
You cannot assign to an array type. Array types are not suitable for a LHS argument for an assignment operator.This is what basically throws the error you see, but if you adhere to #1, you'll never reach here.
You are declaring the fixed size arrays in the struct.
Maybe you want to do this:
struct carinfo_t {
char *brand;
char *model;
int year;
float value;
};
It seems you may have mistyped the definition of your struct.
Maybe change it to something like this:
struct carinfo_t {
char* brand;
char* model;
int year;
float value;
};
The reason you are getting that error is because you are trying to assign the pointer returned by malloc to an array. That won't work. You should instead be storing the pointer returned by malloc in a char*.

Passing a struct into a generic function in C

I declare a new struct with the name of "Struct"
I have a generic function that takes in an argument "void *data".
void Foo(void *data)
I pass an instance of "Struct" into the generic function.
Struct s;
Foo(&s);
I want to access one of the properties of the struct in the function.
void Foo(void *data) {
char *word = (char*) data.word;
}
It's not allowed because it doesn't recognize data as a valid struct.
I even try to declare the data as the struct type first, and I get an error.
void Foo(void *data) {
Struct s = (Struct) data;
char *word = s.word;
}
I get "conversion to non-scalar type requested".
First of all, you should turn on your compiler's warning flags (all of them). Then you should pass a pointer to your Struct and use something other than struct as a variable name:
Struct s;
Foo(&s);
Then, in Foo:
void Foo(void *data) {
Struct *s = data;
char *word = s->word;
}
You can't convert non-pointer types to and from void* like you're trying to, converting pointer types to and from void* is, on the other hand, valid.
You need to pass a pointer to you struct and get a pointer to the struct inside the function:
Struct struct;
Foo(&struct);
void Foo(void *data) {
Struct* struct = (Struct*) data;
char *word = struct->word;
}
You have to use -> operator when requesting structure member via pointer.
This should work: char *word = (char*) data->word;
You also have to pass the address of the structure to the function. Like this: Foo(&struct);.
Firstly you need to call the function correctly:
Struct s;
Foo(&s);
Notice you're now passing a pointer to the structure.
Now, the function has to know that you're using a Struct (as opposed to something else) - perhaps because of another parameter, or a global variable, or some other reason. Then inside the function you can do:
void Foo(void *data) {
Struct *structpointer = p; /* Note - no need for a cast here */
/* (determine whether data does refer to a pointer then...) */
char *word = structpointer->word;
/* ... then use 'word'... */
}
Data is pointer, so whatever you cast it to must also be a pointer. If you said Struct* myStruct = (Struct*) data, all would be well with the world.
You are mixing pointers and data.
Struct struct defines a data object
void *data expects data to be a pointer.
Call Foo with a pointer to a Struct, and make other necessary changes
Struct struct;
Foo((void*)&struct);
void Foo(void *data) {
Struct *struct = (Struct*)data;
char *word = struct->word;
}
or the more compact form:
Struct struct;
Foo((void*)&struct);
void Foo(void *data) {
char *word = ((Struct*)data)->word;
}

Passing char array to struct member

I have the following structure:
struct hashItem {
char userid[8];
char name[30];
struct hashItem *next;
};
In the function below I take a char pointer (char array) argument that I wish to assign to the struct.
void insertItem(struct hashItem *htable[], char *userid, char *name)
{
int hcode = hashCode(userid);
struct hashItem *current = htable[hcode];
struct hashItem *newItem = (struct hashItem*) malloc(sizeof(struct hashItem));
newItem->userid = userid;
newItem->name = name;
[...]
}
Instead I get the following error:
hashtable.c: In function ‘insertItem’:
hashtable.c:62: error: incompatible types in assignment
hashtable.c:63: error: incompatible types in assignment
Line 62 and 63 are the `newItem->..." lines.
You almost certainly don't want to just assign the char* to the char[] - as the compiler points out, the types are incompatible, and the semantics are not what you think. I assume you want the struct members to contain the values of the two char* strings - in which case, you want to call strncpy.
strncpy(target, source, max_chars);
You should chang your struct in
struct hashItem {
char userid[8];
char *name;
struct hashItem *next;
};
to assign a char pointer to a name. In the struct you defined
char name[30] are just 30 chars.
You can't assign a pointer to a string to a character array like you are trying to. Instead you need to copy the contents of the string with strncpy as Adam indicated:
strncpy (newItem->userid, userid, 8);
When you declare the struct with a character array in it, you are allocating memory inside the structure itself to store a string of the given length.
When you pass a pointer into your function, you are passing a memory address (an integer) that indicates where a null-terminated string can be found.
To assign the pointer to the array doesn't make sense. The array has memory allocated for it already -- it can't be made to "point" to another location.
While you can use pointers in your structure, you need to be very careful that when you assign them, you are telling them to point to something that is going to be valid for the duration of the time you will use the structure. For example, this code is bad, because the string passed to insertItem no longer exists after fillStructure returns:
struct hashItem
{
char * userid;
};
void insertItem (struct hashItem * item, char * userid)
{
item->userid = userid;
}
void fillStructure (struct hashItem * item)
{
const char string[] = "testing";
insertItem (item, string);
}
int main(void)
{
struct hashItem item;
fillStructure (&item);
/* item->userid is now a dangling pointer! */
}
For more, I would recommend reading the "Arrays and Pointers" chapter of the C FAQ -- start with Question 6.2 and keep reading from there.

Resources