I have a question regarding the allocation of memory for a given char pointer inside a struct. The following typedef bson_value_t is given by an API and I would like to use it inside my own typedef ObjectInfo, shown in my code:
typedef struct _bson_value_t {
bson_type_t value_type;
union {
int64_t v_int64;
int32_t v_int32;
int8_t v_int8;
double v_double;
struct {
uint32_t len;
char *str;
} v_utf8;
} value;
} bson_value_t;
typedef struct _ObjectInfo {
char key[100];
bson_value_t value;
} ObjectInfo;
I have other data packages that contain hundreds of these ObjectInfo types, but all simply initalized like:
typedef _DataPackage {
ObjectInfo single;
ObjectInfo multiple[100];
...
} Datapackage;
So they do not contain any usefull data yet. I would like to use strcpy to put a string to the location where char *str is pointing. But as far as I know that does not work because there is no allocated memory where *str is pointing to, right?
My question would be, how do I accomplish that without changing the given typedef bson_value_t? Do I need to allocate memory for any one bson_value_t that I initialized?
strcpy(DataPackage.single.value.value.v_utf8.str, "test");
That does not work, unless I change it to:
strcpy(&DataPackage.single.value.value.v_utf8.str, "test");
but this is giving me compiler warnings.
I would like to use strcpy to put a string to the location where char *str is pointing. But as far as I know that does not work because there is no allocated memory where *str is pointing to, right?
Right.
My question would be, how do I accomplish that without changing the given typedef bson_value_t? Do I need to allocate memory for any one bson_value_t that I initialized?
No, you do not (for this purpose) need to dynamically allocate memory for any bson_value_t. The space, if any, to which any of those value.v_utf8.str members point will be external to the the bson_value_t, so arranging for that memory is a separate consideration.
As far as the data structure itself is concerned, the string data could be dynamically allocated, or they could be statically allocated (such as the contents of a string literal), or they could even be a locally-declared array (automatically allocated), though this last will present issues if the lifetime of the string data is shorter than that of the bson_value_t.
However, do make sure that you know what assumptions are made by the library from which you are drawing this. For example, if any of its functions assume that they can reallocate space to provide for lengthening the string, or if they assume that they can modify the contents in place, then such assumptions affect what kind of storage you need to provide.
Related
I am putting together a project in C where I must pass around a variable length byte sequence, but I'm trying to limit malloc calls due to potentially limited heap.
Say I have a struct, my_struct, that contains the variable length byte sequence, ptr, and a function, my_func, that creates an instance of my_struct. In my_func, my_struct.ptr is malloc'd and my_struct is returned by value. my_struct will then be used by other functions being passed by value: another_func. Code below.
Is this "safe" to do against memory leaks provided somewhere on the original or any copy of my_struct when passed by value, I call my_struct_destroy or free the malloc'd pointer? Specifically, is there any way that when another_func returns, that inst.ptr is open to being rewritten or dangling?
Since stackoverflow doesn't like opinion-based questions, are there any good references that discuss this behavior? I'm not sure what to search for.
typedef struct {
char * ptr;
} my_struct;
// allocates n bytes to pointer in structure and initializes.
my_struct my_func(size_t n) {
my_struct out = {(char *) malloc(n)};
/* initialization of out.ptr */
return out;
}
void another_func(my_struct inst) {
/*
do something using the passed-by-value inst
are there problems with inst.ptr here or after this function returns?
*/
}
void my_struct_destroy(my_struct * ms_ptr) {
free(ms_ptr->ptr);
ms_ptr->ptr = NULL;
}
int main() {
my_struct inst = my_func(20);
another_func(inst);
my_struct_destroy(&inst);
}
I's safe to pass and return a struct containing a pointer by value as you did it. It contains a copy of ptr. Nothing is changed in the calling function. There would, of course, be a big problem if another_func frees ptr and then the caller tries to use it or free it again.
Locality of alloc+free is a best practice. Wherever possible, make the function that allocates an object also responsible for freeing it. Where that's not feasible, malloc and free of the same object should be in the same source file. Where that's not possible (think complex graph data structure with deletes), the collection of files that manage objects of a given type should be clearly identified and conventions documented. There's a common technique useful for programs (like compilers) that work in stages where much of the memory allocated in one stage should be freed before the next starts. Here, memory is only malloced in big blocks by a manager. From these, the manager allocs objects of any size. But it knows only one way to free: all at once, presumably at the end of a stage. This is a gcc idea: obstacks. When allocation is more complex, bigger systems implement some kind of garbage collector. Beyond these ideas, there are as many ways to manage C storage as there are colors. Sorry I don't have any pointers to references (pun intended :)
If you only have one variable-length field and its size doesn't need to be dynamically updated, consider making the last field in the struct an array to hold it. This is okay with the C standard:
typedef struct {
... other fields
char a[1]; // variable length
} my_struct;
my_struct my_func(size_t n) {
my_struct *p = malloc(sizeof *p + (n - 1) * sizeof p->a[0]);
... initialize fields of p
return p;
}
This avoids the need to separately free the variable length field. Unfortunately it only works for one.
If you're okay with gcc extensions, you can allocate the array with size zero. In C 99, you can get the same effect with a[]. This avoids the - 1 in the size calculation.
I have been churning through C for the last several months. In an effort to learn the language, the project is an arithmetic parser - formulas, variables, etc.
I recently decided to go ahead and work out garbage collection because I have a lot of calls to this method:
char* read_token(const Source* source, const Token* token) {
int szWord = token->t_L + 1; // +1 for NULL terminator
char* word = (char*)malloc(sizeof(char)*szWord);
memset(word, '\0', sizeof(char)*(szWord));
char* p_T = source->p_Src + token->t_S;
memcpy(word, p_T, token->t_L);
return word;
}
... which means calling free(...) quite a bit.
The Source struct has two buffer properties among others:
typedef struct source Source;
struct source {
// ...
char* p_Src; // malloc'd source buffer
int srcLen;
Token* p_tokens; // malloc'd Token buffer
// ...
};
The Token struct has start and length properties:
typedef struct token Token;
struct token {
int t_S; // buffer start index
int t_L; // token length
};
In addition, since there could be many sources, a Source* buffer is malloc'd.
When a buffer is malloc'd, the size of the struct is provided (* numStructs). But if a given struct has a buffer that may be allocated at a later time, such as Token*, does that change the size of Source? Is the code in danger of overwriting previously allocated memory?
For some reason I was getting the idea that all of the memory used for a struct, including any buffers, is allocated in a linear manner. If Token* buffer in struct is allocated to 10 tokens, that space is not then linearly allocated within the Source struct right?
The pointer members in your struct are variables that store addresses of memory blocks and as you state yourself pointers and pointees are allocated independently. Hence those buffers might be located just next to where their 'parent' struct is stored, or not (and most probably won't).
If it is needed, ensuring contiguous storage of the struct members and its pointed buffers can be achieved by allocating everything in one call to the *alloc function.
This can be done
using fixed-size buffers: not really convenient since any flexibility on the buffer sizes is lost. Also note that declaring this updates the value of sizeof(struct foo) accordingly.
using C99's flexible array member or tricks to enable the feature in pre-C99 C: Allocate Pointer and pointee at once .
using not recommended hacks resorting on pointer arithmetic, watching out for the compiler's alignment policy.
A pointer in a struct is a fixed size, regardless of what it is pointing at, even if it is uninitialised. That way, sizeof(struct token) is a fixed length.
When malloc is used, the memory is taken somewhere from the heap, we know not where, and should not care either. It is highly unlikely that memory will be allocated anywhere near the original struct, and even if it was, that would be implementation specific and you could not count on that behaviour.
Obviously (?) you should call free() on the pointer before the struct that it lives in is destroyed.
Also note C99's Variable Length Arrays (VLAs).
Sorry, i'm writing this in the "Answer" section instead of "Comments" section because my Stackoverflow reputation isn't high enough yet.
What i was about to comment is Why don't you just use this line:
char word[ sizeof(char)*szWord ];
instead of
char* word = (char*)malloc(sizeof(char)*szWord); ?
typedef struct {
char manufacturer[SIZE];
char model[SIZE];
int size;
int id;
int qty;
double cost;
double price;
} tv;
void firstSix(tv *tvarr[]);
void firstSix(tv *tvarr[])
{
(*tvarr[0]).manufacturer = "Vizio";
}
I am making an inventory program. It consists of an array of structs that will store information about different televisions. In my program I am required to hardcode six entries into the array, so I am trying to make a function that will take a struct array pointer argument. In the above code, I included the struct declaration, the function prototype and function definition that I am trying to make. Everything is placed before and after main in the respective order. I don't understand why Visual Studio is highlighting the first parenthesis in the code inside the function definition and saying "expression must be a modifiable lvalue". I don't understand what it is that I am doing wrong. Please help.
You cannot assign an array like that. You need to do
strcpy ((*tvarr[0]).manufacturer, "Vizio");
Make sure that you don't go out of bounds when copying the string into the array.
You can either check the size of the string in advance or use strncpy which will limit the maximum number of characters to be copied.
An array is not a modifiable l-value. So basically you cannot have it on the left hand side of an assignment.
Or may be you also might want to define manufacture as char *manufacture and then dynamically allocate the string.
manufacturer = strdup ("Vizio"); //manufacturer is char *
Or depending on the length first allocate the buffer
manufacturer = malloc (sizeof (char) * needed_bytes);
Whenever you dynamically allocate the buffer, whenever you have finished working with it always remember to free it free (manufacturer).
I think you want to do something like
strncpy((tvarr[0])->manufacturer, "Vizio", SIZE - 1);
Kevin has it; you can't assign a string to a pointer, you must copy the data to the array. I suggest strncpy to keep from running off the end of the allocated space.
This seems to be a very simple problem but I can't quite figure out which part is causing it. Basically, I have a struct that just contains an array of strings
struct command_stream{
char **tokens;
};
typedef struct command_stream *command_stream_t;
command_stream_t test;
Then later on, I parse some strings into shorter ones and end up with another array of strings
char **words = *array of strings*
words contains the correct information I want, I looped through and printed out each element to make sure I wasn't getting a faulty string. So now I just point tokens to words
test->tokens = words;
But it gives me a segmentation fault. I'm not sure why though. They're both pointers, so unless I'm missing something obvious...
EDIT: The function as a whole has to return a pointer, which is why it was set up like this, which I keep forgetting. But I think I've got it, if I just create a new typedef
typedef struct command_stream command_stream_s;
command_stream_s new_command_stream;
and just return
&new_command_stream;
That should work right? Even though new_command_stream itself isn't a pointer.
From your code excerpt, it seems that you have not declared the struct. You have successfully declared a pointer to the struct command_stream_t test; but this pointer does not point to anywhere yet.
You need to allocate memory for your struct in some way and make test reference it. For instance:
command_stream_t test =
(command_stream_t) malloc(sizeof(struct command_stream));
This way you can successfully use:
test->tokens = words;
as you intended.
Note that you don't need to use malloc to allocate the memory. The pointer can reference a local/global variable as long as it has memory associated to it (N.B. if you use a local var don't use the pointer outside the declaration scope of that var).
typedef struct command_stream *command_stream_t;
command_stream_t test;
This makes "test" a pointer. There is no memory allocated for the structure.
You need to allocate memory for the structure and make the test pointer point to the block of memory before you can dereference by saying -
test->tokens = words;
Do this:
typedef struct command_stream command_stream_t;
command_stream_t test;
test.tokens = words;
The difference is that, command_stream_t is no more a pointer type, it is the actual structure.
I made a struct like this:
struct a{
char *name;
char *value;
struct a *next;
};
when I malloc for memory at first time, it's ok, and I can set 'name' and 'value' a corresponding value.
but when I malloc for the second time, errors come. And It's a cgi, just show me "500 Internal server error".
I changed the pointer 'name' and 'value' to array, everything works.
I thought maybe the complier doesn't know how much memory to assign.
And do you have some ideas with this? I will appreciate every answer!
struct a {
char *name;
char *value;
struct a *next;
};
struct a *head = malloc(sizeof *head);
The above allocates space for a single struct a object, but it doesn't initialize any of hte three pointers contained in a struct a. In particular, if you want name and value to point to strings, you'll need to allocate space for those strings:
head->name = malloc(5);
strcpy(head->name, "Fred");
head->value = malloc(8);
strcpy(head->value, "abcdefg";
This is considerably oversimplified. 5 and 8 are "magic numbers"; you should specify the sizes in a way that will remain consistent if you change the initial values. And you should always check whether malloc() returns a null pointer (even if you just terminate the program with an error message).
If you don't initialize name and value to point to some chunk of allocated memory, you might still be able to initialize what they point to (e.g., by doing the strcpys above without the mallocs). More precisely, the system won't necessarily diagnose the error.
Finally, you'll need a call to free() corresponding to each malloc() call.
Note that this is largely a guess based on your description. If you can show us your actual code, we can help you better.
If you use malloc with sizeof(struct a) it's just going to assign enough space to store the pointers name and value. You want these to be char arrays, then it'll know how much space to set aside for each instance of a.