typedef struct unit_class_struct {
char *name;
char *last_name;
} person;
int setName(person *array) {
array[0].name = strdup("Bob");
array[1].name = strdup("Dick");
return 1;
}
int setLastName(person *array) {
array->last_name = strdup("Sanchez");
array++;
array->last_name = strdup("Clark");
return 1;
}
int main()
{
person array[10];
person *pointer;
pointer = array;
setName(pointer);
setLastName(pointer);
printf("First name is %s %s\n", array[0].name, array[0].last_name);
printf("Second name is %s %s\n", array[1].name, array[1].last_name);
while(1) {}
return 0;
}
This is some example code I came up with to play around with structures.
Notice the way I set the name in setName and the way I did it in setLastName.
Both work, but I'm curious whats the difference between the two ways I did it?
Is one way better than the other?
Also is strdup necessary in this example? If not, would it be necessary if I was setting array.name to random sized variables rather than string literals?
If you set all your .name's to string constants, then no, strdup is not strictly needed. You'll want it if you're going to modify the string later. A better grounding in pointer's and memory management will make the distinction clear. If you do use strdup, be sure to free the result later.
Both options are quite risky, because you donĀ“t know the length of the array. Consequently, accessing the result of array++ or array[1] could result in undefined behaviour.
Perhaps you could try this apprach
int set_last_name(person* array, char* lastnames[],size_t amount){
int i=0;
for(;i<amount;i++,array++){
strncpy(array->lastname,lastnames[i],strlen(lastnames[i]));
}
return 1;
}
where amount is the length of the lastnames array.
Note that theres no usage of strdup. This function would expect the user to allocate memory for lastnames and array. Then the user should free that memory , if needed.
I dislike strdup because it returns a heap allocated string, and in the case of your functions, it should be clearly documented that the user of the functions has to free it.
Using the indexed approach is slightly clearer than using the pointer arithmetic, in my opinion but either works. I suspect the code the compiler generates for each is quite similar in both instances.
strdup is necessary in this instance if you're working with variables because you do not allocate memory to save your string values in in the person struct. If you'd already allocated space for those strings when either of your setters was called, strcpy (strcpy_s, preferably) would be sufficient.
When working with literals as you are in your example, strdup is not necessary: you can assign directly to the char*.
array->name is exactly the same as (*array).name.
In both your functions "array" is a pointer to a structure, so both *array and array[0] are structures, and you can set their members. The arrow notation is just a often used shortcut.
Related
I'm trying to add a string at the end of pointer to pointer in C, I'm using the below code the problem is I can't free what I have allocated as the pointer to pointer has values that were not all allocated memory, How can I add string at the end of a pointer to pointer properly?
int add_environ(char *str, char **envp)
{
char **r;
int i;
r = envp;
i = 0;
while (r[i])
{
i++;
}
//how can I add string without using malloc?
// my problem is I can't free this allocated memory
r[i] = malloc(strlen(str));
if (r[i])
{
r[i] = str;
r[++i] = 0;
return (1);
}
return (0);
}
If your question only targets environmental variables, then I would go with setenv. If not, Waxrat gave you one solution. Oh, btw: You're assuming in your code, that envp is arbitrarily long. That's not true either, so your code will crash sooner or later. Depending on your exact requirements, I would suggest to create a deep copy of envp in main and then only operate on that copy, because then everything is malloced and needs to be freed, so nothing special to track any longer.
You'd need to remember somehow which items in the *envp array came from the heap. For example, by storing them in another array of pointers. There's no real general way to do what you describe, you'd need to do something context specific.
I have a small program that creates a semver struct with some variables in it:
typedef struct {
unsigned major;
unsigned minor;
unsigned patch;
char * note;
char * tag;
} semver;
Then, I would like to create a function which creates a semver struct and returns it to the caller. Basically, a Factory.
That factory would call an initialize function to set the default values of the semver struct:
void init_semver(semver * s) {
s->major = 0;
s->minor = 0;
s->patch = 0;
s->note = "alpha";
generate_semver(s->tag, s);
}
And on top of that, I would like a function to generate a string of the complete semver tag.
void generate_semver(char * tag, semver * s) {
sprintf( tag, "v%d.%d.%d-%s",
s->major, s->minor, s->patch, s->note);
}
My problem appears to lie in this function. I have tried returning a string, but have heard that mallocing some space is bad unless you explicitly free it later ;) In order to avoid this problem, I decided to try to pass a string to the function to have it be changed within the function with no return value. I'm trying to loosely follow something like DI practices, even though I'd really like to separate the concerns of these functions and have the generate_semver function return a string that I can use like so:
char * generate_semver(semver * s) {
char * full_semver;
sprintf( full_semver, "v%d.%d.%d-%s",
s->major, s->minor, s->patch, s->note);
return full_semver; // I know this won't work because it is defined in the local stack and not outside.
}
semver->tag = generate_semver(semver);
How can I do this?
My problem appears to lie in this function. I have tried returning a string, but have heard that mallocing some space is bad unless you explicitly free it later.
Explicitly freeing dynamically allocated memory is required to avoid memory leaks. However, it is not necessarily a task that the end users need to perform directly: an API often provides a function to deal with this.
In your case, you should provide a deinit_semver function that does the clean up of memory that init_semver has allocated dynamically. These two functions behave in a way that is similar to constructor and destructor; init_semver is not a factory function, because it expects the semver struct to be allocated, rather than allocating it internally.
Here is one way of doing it:
void init_semver(semver * s, int major, int minor, int pathc, const char * note) {
s->major = major;
s->minor = minor;
s->patch = pathc;
size_t len = strlen(note);
s->note = malloc(len+1);
strcpy(s->note, note);
s->tag = malloc(40 + len);
sprintf(s->tag, "v%d.%d.%d-%s", major, minor, patch, note);
}
void deinit_semver(semver *s) {
free(s->note);
free(s->tag);
}
Note the changes above: rather than using fixed values for the components of struct semver, this code takes the values as parameters. In addition, the code copies the note into a dynamically allocated buffer, rather than pointing to it directly.
The deinit function does the clean-up by free-ing both fields that were allocated dynamically.
A char * on its own is just a pointer to memory. To accomplish what you want you will either need to instead use a fixed size field, i.e. char[33], or you can dynamically allocate the memory as needed.
As it is, your generate_semver function is attempting to print to an unknown address. Let's look at one solution.
typedef struct {
unsigned major;
unsigned minor;
unsigned patch;
char note[32];
char tag[32];
} semver;
Now, in your init_semver function, the line previously s->note = "alpha"; will become a string copy, as arrays are not a valid lvalue.
strncpy(s->note, "alpha", 31);
s->note[31] = '\0';
strncpy will copy a string from the second parameter to the first up to the number of bytes in the third parameter. The second line ensures that a trailing null terminator is in place.
Similarly, in the generate_semver function, it would directly work in the buffer:
void generate_semver(semver * s) {
snprintf( s->tag, 32, "v%d.%d.%d-%s",
s->major, s->minor, s->patch, s->note);
}
This will directly print to the array in the structure, with a maximum character limit. snprintf does append a trailing null terminator (unlike strncpy), so we don't need to worry about adding it ourselves.
You mention having to free allocated memory, and then say: "In order to avoid this problem". Well, it's not so much a problem, but rather a necessity of the C language. It's common to have functions that allocate memory, and require the caller to free it again.
The idiomatic way is to have a pair of "create" and "destroy" functions. So I'd suggest doing it like this:
// Your factory function
semver* create_semver() {
semver* instance = malloc(sizeof(*instance));
init_semver(instance); // will also allocate instance->tag and ->note
return instance;
}
// Your destruction function
void free_semver(semver* s) {
free(semver->tag);
free(semver->note);
free(semver);
}
I'm attempting to make an array of the structure I made called StatusItem, which looks like this:
typedef struct
{
char* name;
char* index;
int optional;
} StatusItem;
Also, as I want this array to be of any size, I am using malloc. So the array is defined as such:
StatusItem* statusItem = NULL;
(its then passed to function which retrieves all the values as follows.)
statusItem = (StatusItem*)malloc(cJSON_GetArraySize(items));
...
for (i = 0 ; i < cJSON_GetArraySize(items) ; i++)
{
strcpy(statusItem[i].name,name->valuestring);
strcpy(statusItem[i].index,index->valuestring);
if(!parseInt(optional->valuestring, &statusItem[i].optional));
{
goto cleanup;
}
}
There's come code that involves the cJSON library in getting the string values of name, index and optional into the variables referenced above, and they are stored in the valuestring field of those variables.
I have checked that everything involving the cJSON library works fine, and returns the correct values, but the program is unable to access or store values in the statusItems array.
Any ideas? I'm almost positive that it involves some misuse of malloc on my part.
1) cJSON_GetArraySize(items) returns an element count - you need the size of the object factored in: malloc(cJSON_GetArraySize(items) * sizeof(StatusItem))
2) a StatusItem structure doesn't have memory for the actual string - only a pointer to a string. You can use strdup() to allocate and copy a string.
You probably want your code to look more like:
statusItem = (StatusItem*)malloc(cJSON_GetArraySize(items) * sizeof(StatusItem));
...
for (i = 0 ; i < cJSON_GetArraySize(items) ; i++)
{
statusItem[i].name = strdup(name->valuestring);
statusItem[i].index = strdup(index->valuestring);
if(!parseInt(optional->valuestring, &statusItem[i].optional));
{
goto cleanup;
}
}
Of course this means that you also have to free the duplicated strings explicitly when you free the array of StatusItem objects:
// to free the statusItem array, and the various strings it refers to:
for (i = 0 ; i < cJSON_GetArraySize(items) ; i++)
{
free(statusItem[i].name);
free(statusItem[i].index);
}
free(statusItem);
Two misuses spotted:
Don't cast the return value of malloc(), it's dangerous and superfluous.
You don't allocate any memory for the members of the structure - you're strcpy()ing to uninitialized pointers, so your program invokes undefined behavior.
Edit: actually three:
malloc(cJSON_GetArraySize(items));
doesn't allocate enough memory since it's not magic and it doesn't know you're reserving sizeof(StatusItem) bytes of memory, thus you have to multiply the allocation size by sizeof(StatusItem), or even better, by sizeof(*statusItem) for safety.
In addition, malloc takes a number of bytes, not elements. The value passed to it must be multiplied by the size of each element.
To avoid having to use strdup() which is a little 'messier' because it leaves the freeing of the memory up to the caller instead of taking care of everything itself, I modified my existing structure as follows:
typedef struct
{
char name[32];
char index[32];
int optional;
} StatusItem;
This allows 32 bytes for the name and index, which should be more than enough. Before, the structures fields were pointing to nothing, which was causing the error when trying to copy to that location. now, there is empty (or junk) memory waiting for the string to be placed in.
This allows for strcpy() to still be used, and allows for an overall cleaner implementation.
I'm pretty new at C programming, and this type of thing keeps popping up. As a simple example, suppose I have a struct http_header with some char pointers:
struct http_header {
char* name;
char* value;
};
I want to fill an http_header where value is the string representation of an int. I "feel" like, semantically, I should be able to write a function that takes in an empty header pointer, a name string, and an int and fills out the header appropriately.
void fill_header(struct http_header *h, char* name, int value)
{
h->name = name;
char *value_str = malloc(100);
sprintf(value_str, "%d", value);
h->value = value_str;
}
int main(int argc, const char * argv[])
{
struct http_header h;
char *name = "Header Name";
int val = 42;
fill_header(&h, name, val);
...
free(h.value);
}
Here, the calling code reads exactly as my intent, but in this case I'm creating the value string dynamically, which means I'd have to free it later. That doesn't smell right to me; it seems like the caller then knows too much about the implementation of fill_header. And in actual implementations it may not be so easy to know what to free: consider filling an array of http_headers where only one of them needed to have its value malloced.
To get around this, I'd have to create the string beforehand:
void fill_header2(struct http_header *h, char* name, char *value_str)
{
h->name = name;
h->value = value_str;
}
int main(int argc, const char * argv[])
{
struct http_header h;
char *name = "Header Name";
int value = 42;
char value_str[100];
sprintf(value_str, "%d", value);
fill_header2(&h, name, value_str);
}
As this pattern continues down the chain of structures with pointers to other structures, I end up doing so much work in top level functions the lower level ones seem hardly worth it. Furthermore, I've essentially sacrificed the "fill a header with an int" idea which I set out to write in the first place. I'm I missing something here? Is there some pattern or design choice that will make my life easier and keep my function calls expressing my intent?
P.S. Thanks to all at Stackoverfow for being the best professor I've ever had.
Well, I would go with the first approach (with a twist), and also provide a destroy function:
struct http_header *make_header(char *name, int value)
{
struct http_header *h = malloc(sizeof *h);
/* ... */
return h;
}
void destroy_header(struct http_header *h)
{
free(h->name);
free(h);
}
This way the caller doesn't have to know anything about http_header.
You might also get away with a version that leaves the main allocation (the struct itself) to the caller and does it's own internal allocation. Then you would have to provide a clear_header which only frees that fill allocated. But this clear_header leaves you with a partially-valid object.
I think your problem is simply that you are programming asymmetrically. You should once and for all decide who is responsible for the string inside your structure. Then you should have two functions, not only one, that should be called something like header_init and header_destroy.
For the init function I'd be a bit more careful. Check for a 0 argument of your pointer, and initialize your DS completely, something like *h = (http_header){ .name = name }. You never know if you or somebody will end up in adding another field to your structure. So by that at least all other fields are initialized with 0.
If you are new at C programming, you might perhaps want to use the Boehm's conservative garbage collector. Boehm's GC works very well in practice, and by using it systematically in your own code you could use GC_malloc instead of malloc and never bother about calling free or GC_free.
Hunting memory leaks in C (or even C++) code is often a headache. There are tools (like valgrind) which can help you, but you could decide to not bother by using Boehm's GC.
Garbage collection (and memory management) is a global property of a program, so if you use Boehm's GC you should decide that early.
The general solution to your problem is that of object ownership, as others have suggested. The simplest solution to your particular problem is, however, to use a char array for value, i.e., char value[12]. 2^32 has 10 decimal digits, +1 for the sign, +1 for the null-terminator.
You should ensure that 1) int is not larger than 32-bits at compile-time, 2) ensure that the value is within some acceptable range (HTTP codes have only 3 digits) before calling sprintf, 3) use snprintf.
So by using a static array you get rid of the ownership problem, AND you use less memory.
I'm trying to hunt down memory leaks and have found one source. I am malloc'in the pointer in one function and freeing it in another, but I'm missing out on understanding how to copy the value the pointer points to while also being able to free the pointer.
Current implementation (with memory leak):
// This code has been greatly simplified
// and as such does not appear to have any purpose
int foo(){
int bestval = 0;
char *best;
char *match;
for (int i=0;i<3;i++) {
int returnValue = bar(&best);
if (returnValue > 10) {
(1)
match = best;
}
}
printf("%s", match);
(2)
return 0;
}
int bar(char ** best) {
char*s = "Hello!";
*best = malloc(strlen(s) + 1);
strcpy(*best,s);
return 0;
}
Two questions
If I had to free memory at (1) rather than (2), how would I do it so that match would still have what was contained in best?
Should I be doing strcpy to copy best to match? If so, do I have to do another malloc within foo?
A bit of a stab in the dark, assuming there's a loop in Foo...
int foo()
{
int bestval = 0;
char *best;
char *match = 0; // initialize to null
// start some loop
for (int i=0;i<3;i++) {
// fetch the next best value...
int returnValue = bar(&best);
// some check (if best is really best!)
if (returnValue > 10) {
// if match has previously been populated, free it
if(match) {
free(match);
}
// save the new best value
match = best;
}
else {
// not saving best in match, so free it!
free(best);
}
}
// end some loop
// only do this if match was successful?!?
if(match) {
printf("%s", match);
// clean up once the best of the best has been used...
free(match);
}
return 0;
}
In function bar the strcpy should read as
strcpy(*best,s);
In the main function you can copy the value best points to by
strcpy(match, best);
free(best);
match needs to point to a valid memory block before. If you do a
match = best;
free(best);
match will be invalid too because it points at the same freed memory best pointed.
You need to know the size of the string.
At (1) You would be assigning the address of a memory address that has already been freed, you have to do another malloc to match*=malloc(sizestr) and then copy it with memmove or strcpy if you want to free best.
If I understood properly, you want to copy the string into best, then free bests memory and assign ptr to match? if you free best memory before memmoving or strcpying to another location you lose its contents, and if you want to copy it to another location first you need to allocate the memory where you want to copy it to, so you need 2 mallocs on that code.
If I had to free memory at (1) rather than (2), how would I do it so that match would still have what was contained in best?
If you free at position (1), it is not possible to do it so that match would still have what was contained in best.
Should I be doing strcpy to copy best to match? If so, do I have to do another malloc within foo?
match = best;
With the above statement, both are pointing to the same location. So, there is no need to strcpy at all. To do that, allocate memory for match to point to whose length is best+1 and then do a strcpy.
Copying the value of a pointer does not copy the underlying memory. So either, don't free(best) until you are done with match, or you will need to malloc a new buffer, and e.g. memcpy() the contents from one buffer to the other.
Yes, you can malloc and strcpy:
match = malloc(strlen(best) + 1);
strcpy(match, best);
But, if your implementation provides it you can use the strdup() function which is much easier:
match = strdup(best);
If you don't already have strdup(), it's a good idea to create one yourself.
Your current assignment simply assigns the pointers to the same buffer. If you then free() this buffer, you've removed what is contained here (and thus dereferencing it is a bad idea).
You don't need to use strcpy() to copy best to match - you'll be better off freeing it after the printf() (or the last point that it is needed). There's no point over-complicating things with an extra function call or six, just remember to free() memory that you've allocated at the end of each function!