I have created an array of structure Human which consists of char *name
.
I use function like this:
Human *createHuman(char *name){
Human *h = malloc(sizeof(Human));
h->name = strdup(name);
return h;
}
I have tested this function, it works perfectly, but my problem starts when i use it like this:
void gen_Humans(Human array[MAX], int n){
//n == max;
for (int i = 0; i<n; i++){
char *name = gen_name_function_used_before_WORKING();
array[i] = *createHuman(*name);
}
…
}
As I said, if I generate one human it works just fine.
I debugged my code and when I got to the point of strdup(name)
it threw me this:
my error: Exception thrown at 0x53DCF6E0 (ucrtbased.dll) in project.exe:
0xC0000005: Access violation reading location 0x00000070.
I am using VS 2017 Enterprise.
When calling your function createHuman
you are passing the value of your name:
array[i] = *createHuman(*name);
When building this application, Iam getting the following compiler warning (GCC):
warning: passing argument 1 of 'createHuman' makes pointer from integer without a cast
since your function createHuman
expects the adress of the name, you should also pass the address. For example:
array[i] = *createHuman(name);
Adding to @MortizSchmidt's answer:
- You are not checking the results of
malloc()
. You should do so, even if the chances of failure are small.
- You are leaking memory - since you never free the
malloc()
ed memory nor do you keep the pointer anywhere. Remember C is not like Java - assignment is not an assignment of a reference.
- Note that the
MAX
indicator in the function signature doesn't have any effect. The parameter is an int* any way you write it: int* array
, int array[]
or int array[MAX]
.
Actually, why even allocate the Human structure rather than just space for the string?
struct Human createHuman(char *name){
if (name == NULL) {
struct Human h = { NULL };
return h;
}
struct Human h = { strdup(name) };
if (h.name == NULL) { /* handle error here */ }
return h;
}
void gen_Humans(Human array[MAX], int n){
for (int i = 0; i < n; i++) {
char *name = gen_name_function_used_before_WORKING();
array[i] = createHuman(name);
}
…
}
This has the added benefit of initializing all fields in Human
after name
to 0.