how to use memcpy to initialize a char pointer in struct - c

this is how I define struct.
struct urlFormat
{
int port;
char *host;
char *path;
int cat;
char *status;
};
this is how I initialize strcut and allocate the space for the pointer.
struct urlFormat *res;
res = malloc(sizeof(struct urlFormat));
when I used memcpy() function, it reported segmentation fault.
char *ptr1 = (char *)url;
int len = strlen(ptr1);
memcpy(res->host, ptr1, len);
I don't know how to solve it.

res->host is just a pointer (that is not pointing to anything yet).
Until res->host is pointing to some valid memory you can't memcpy to it.
You can either malloc some memory res->host = malloc(len + 1);(+1 for the 0 terminator and sizeof(char) is always 1 so omit it) or in this case just use res->host = strdup(ptr1);

Related

Why does the malloc order matter when a struct is sufficiently sized?

I ran into an interesting problem today. This snippet prints garbage (e.g. ?Y#??):
typedef struct {
int field_1;
int field_2;
int field_3;
char *arr[64];
} test;
int main(void) {
test *test = malloc(sizeof(test));
char *str = malloc(sizeof(char) * 6);
strncpy(str, "hello", 5);
str[5] = '\0';
test->arr[0] = str;
printf("%s\n", test->arr[0]);
}
However, changing test to:
typedef struct {
int field_1;
int field_2;
char *arr[64];
} test;
(removing field_3) prints the expected result (hello).
Even stranger, swapping the malloc calls like so:
char *str = malloc(sizeof(char) * 6);
test *test = malloc(sizeof(test));
prints the correct result regardless of the size of test.
What the heck is going on here?
I'm using clang-1200.0.31.1.
The problem is on this line:
test *test = malloc(sizeof(test));
Here, sizeof(test) is referring to the variable named test, not the type named test. So you're getting the size of a pointer, not the size of the struct. As a result, you're not allocating enough space for the object in question and you write past the end of allocated memory, invoking undefined behavior.
Give either the typedef or the variable a different name, for example:
typedef struct {
int field_1;
int field_2;
int field_3;
char *arr[64];
} test_type;
...
test_type *test = malloc(sizeof(test_type));

Initialise struct pointers in a function in C

I'm fairly new to C and I'm a little confused as to the correct way to initialise struct variables which are pointers, within a function. Is this style sufficient, or do I need to allocate memory before I assign s->str?
Thank you kindly for your replies, apologies if the question is unclear as I am very new to this language.
typedef struct Mystruct{
const char* str1;
const char* str2;
}mystruct;
mystruct* mystruct_new(const char* str1, const char* str2){
mystruct *s = (mystruct*)(malloc(sizeof(mystruct)));
s->str1 = str1;
s->str2 = str2;
return s;
}
your function is legal and doesn't do anything bad. Nevertheless, you should document it to mention that the strings are not copied, only the pointers are.
So if the passed data has a shorter life than the structure itself, you may meet undefined behaviour. Example:
mystruct*func()
{
char a[]="foo";
char b[]="bar";
return mystruct_new(a,b);
}
mystruct*func2()
{
char *a="foo";
char *b="bar";
return mystruct_new(a,b);
}
int main()
{
mystruct *s = func();
printf(s->a); // wrong, memory could be trashed
mystruct *s2 = func2();
printf(s2->a); // correct
mystruct *s3 = mystruct_new("foo","bar");
printf(s3->a); // also correct, string literals have global scope
}
the above code is undefined behaviour for the first print because s->a points to some memory that is no longer allocated (local to func).
The second print is OK because s2->a points to a string literal which has infinite life span.
So maybe your function is more useful like this:
mystruct* mystruct_new(const char* str1, const char* str2){
mystruct *s = malloc(sizeof(mystruct));
s->str1 = strdup(str1);
s->str2 = strdup(str2);
return s;
}
now the memory is allocated for the strings. Don't forget to free it when discarding the structure, better done in another utility function.
If the strings being passed in to str and str2 will always be string constants than yes you can get away with doing it this way. My guess however is that this is not the case. So you would be better off making a copy of each string with strdup and assigning those to the struct members:
mystruct* mystruct_new(const char* str1, const char* str2){
mystruct *s = malloc(sizeof(mystruct));
s->str1 = strdup(str1);
s->str2 = strdup(str2);
return s;
}
Just make sure to free each of those fields before freeing the struct.
Think of it this way: when you allocate memory for the struct, you get the pointer member variables for free. So in essence, when you do this:
mystruct *s = malloc(sizeof(mystruct)); //don't cast result of malloc.
Then you can treat s->str1 in the exact same way as you would any regular char* variable, say
char *str1 = NULL;
If you want it to point to something, then you have to allocate memory for the pointers. Consider this:
mystruct* mystruct_new(const char* str1, const char* str2){
mystruct *s = malloc(sizeof(mystruct);
char* someString = getMyString(); //gets some arbitrary string
char* str1 = NULL;//just for demonstration
int length = strlen(someString) + 1;
//for struct members
s->str1 = malloc(sizeof(char) * length);
strcpy(s->str1, someString);
//For regular pointers
str1 = malloc(sizeof(char) * length);
strcpy(str1, someString);
return s;
}
Also note that if you just assign to a pointer by using the = operator instead of allocating memory, then it will only copy the address to the original value. This may or may not be what you want depending on the context. Generally, if you know the memory location will stay in scope and you don't need (or don't mind) to change the original string, then it is preferred to simply assign it. Otherwise, it is advisable to make a copy.
//Makes a copy of the string
s->str1 = malloc(sizeof(char) * length);
strcpy(s->str1, someString);
//copies the address of the original value only!
s->str1 = someString;
Use strncpy() instead of strcpy(). The latter is subject to buffer overruns.
For example in this code snippet given by another user, use the strncpy() in place of strcpy()
mystruct* mystruct_new(const char* str1, const char* str2){
mystruct *s = malloc(sizeof(mystruct);
char* someString = getMyString(); //gets some arbitrary string
char* str1 = NULL;//just for demonstration
int length = strlen(someString) + 1;
//for struct members
s->str1 = malloc(sizeof(char) * length);
strcpy(s->str1, someString);
//For regular pointers
str1 = malloc(sizeof(char) * length);
strcpy(str1, someString); // replace with strncpy(str1, someString, bufsize); where bufsize is the maximum number of characters in your string + 1 for the terminator '\0'.
return s;
}

Malloc an array inside a struct

I'm trying to malloc an array inside a struct but I keep getting segmentation errors when I run the program.
The compares function is just something I'm testing so it shouldn't be a part of the problem
typedef struct {
char *string;
} prod_t;
int
main(int agrc, char **argv){
int i = 0;
prod_t *c = NULL;
char str2[100] = "abcd";
c->string = (char *) malloc( 5 * sizeof(char));
strcpy(c->string,str2);
compares(c->stock,str2,i);
return 0;
}
The problem is that you're allocating space for the string, but you're not allocating the struct at all. c remains set to NULL and you're trying to dereference it.
Allocate space for the struct before assigning to its members
prod_t *c = malloc(sizeof(prod_t));
And, as a sidenote for your next-to-fix error: this field doesn't exist
c->stock
You need to allocate space for the struct before you can assign to the string member:
prod_t *c = malloc(sizeof(prod_t));
Also see Do I cast the result of malloc?
First of all, don't cast result of malloc. You only need to do that in C++. In C, it can actually hide potential problems.
Second of all, you need to allocate (or statically declare) your structure.
Third, c->stock doesn't exist. You probably meant c->string.
typedef struct {
char *string;
} prod_t;
int
main(int agrc, char **argv) {
int i = 0;
prod_t *c = malloc( sizeof( prod_t ));
char str2[100] = "abcd";
c->string = malloc( 5 * sizeof(char));
strcpy(c->string,str2);
compares(c->string,str2,i);
return 0;
}

why char buf[] instead of char *buf in redis's sdahdr struct

In redis there is a struct called sdahdr:
struct sdahdr
{
int len;
int free;
char buf[];
}
Why not use char *buf instead, and why is sizeof(sdahdr) == 8 instead of 12?
The char buf[] is a placeholder for a string. Since the max length of the string is not known at compiletime, the struct reserves the name for it, so it can be properly adressed.
When memory is allocated at runtime, the allocation must include the length of the string plus the sizeof the struct, and then can pass around the structure with the string, accessible via the array.
char *s = "test";
struct sdahdr *p = malloc(sizeof(struct sdahdr)+strlen(s)+1);
strcpy(p->buf, s);

how to malloc for this structure

typedef struct testMsg_ {
unsigned char opCode;
unsigned int Count;
char *macsStrList[MAC_ADDR_STR_LEN];
} testMsg_t;
Number of elements in macsStrList is m_Count.
I know following is not correct:
testMsg_t *pInput = (testMsg_t *) malloc(sizeof(testMsg_t) );
This is correct, given the structure you have done
testMsg_t *pInput = (testMsg_t *) malloc(sizeof(testMsg_t) );
However you are probably confused to the meaning of *arr[dimension] -- which is an array length dimension of pointers to chars -- reading between the lines,
MAC_ADDR_STR_LEN
Is probably ment to the legth of the string representation of a mac address (say <20 bytes?)
However your struct gives you 20 char pointers, and the character pointers still have to be initializaed to point to valid memory.
testMsg_t *pInput = (testMsg_t *) malloc(sizeof(testMsg_t) );
pInput->macsStrList[0] = (char *) malloc( MAC_ADDR_STR_LEN+1 );
pInput->macsStrList[1] = (char *) malloc( MAC_ADDR_STR_LEN+1 );
pInput->macsStrList[2] = (char *) malloc( MAC_ADDR_STR_LEN+1 );
...
or redefine your struct to
typedef struct testMsg_ {
unsigned char opCode;
unsigned int Count;
char macsStrList[NUMBER_OF_MAC_ADDRESSES][MAC_ADDR_STR_LEN];
} testMsg_t;
To avoid having to deal with multiple number of allocations.
ADDITION;
As per comments, given that the number of mac addresses are dynamically determined, you could also define the struct as;
typedef struct testMsg_ {
unsigned char opCode;
unsigned int Count;
char macsStrList[1][MAC_ADDR_STR_LEN];
} testMsg_t;
and then allocate it using
testMsg_t *pInput = (testMsg_t *) malloc(sizeof(testMsg_t) + (countOfMacsAddresses * MAC_ADDR_STR_LEN) );
That would have the added over a solution with pointers of that you could use realloc to resize the array dynamically if you needed to do that as well.....
I think what you're looking for is maybe (ok, Soren got in first, but I'll show a way to allocate a single contiguous chunk):
/* assuming we only need macStrList[0] ... [Count-1] */
struct testMsg
{
unsigned char opCode;
unsigned int Count;
char *macsStrList[];
};
struct testMsg *allocate_testMsg(int count)
{
char *string_storage;
struct testMsg *msg;
size_t size = sizeof(struct testMsg) /* base object */
+ (count * sizeof(char *)) /* char* array */
+ (count * (MAC_ADDR_STR_LEN+1)) /* char storage */
;
msg = malloc(size);
msg->Count = count;
string_storage = (char *)&(msg->macStrList[count]);
/* note msg->macStrList points to UNINITIALIZED but allocated storage.
it might be sensible to zero-fill string_storage, depending on how you'll
initialize it
*/
for (count=0; count < msg->Count;
++count, string_storage += (MAC_ADDR_STR_LEN+1))
{
msg->macStrList[count] = string_storage;
}
return msg;
}
Of course it is. You allocate a pointer to a testMsg_t which is an alias for struct testMsg_. However you need to initialize this object yourself.
(And you don't need to cast the allocated pointer in C).

Resources