How to design libraries written in ANSI C? - c

I want to develop a library with ANSI C.
I have a string struct:
struct libme_string
{
char* buffer;
int length;
};
I want to write a function, libme_create_string(), that creates and initializes a string (like constructors in C++).
Which of these methods is better for designing libme_create_string()?
Method #1
Allocate memory for string object in libme_create_string() and return it:
struct libme_string* libme_create_string(int length)
{
// Check arguments...
// Allocate memory for object.
struct libme_string* str = malloc(sizeof(struct libme_string));
// Handle memory allocation errors...
str->buffer = malloc(length);
str->length = length;
// Handle memory allocation errors...
return str;
}
void libme_delete_string(struct libme_string* str)
{
// Check arguments...
free(str->buffer);
free(str);
}
Use
struct libme_string* str;
str = libme_create_string(1024);
// ...
libme_delete_string(str);
str = NULL;
Method #2
Do not allocate memory for string object in libme_create_string() function, accept it as an argument:
struct void libme_create_string(libme_string* str, int length)
{
// Check arguments...
// Just allocate memory for members.
str->buffer = malloc(length);
str->length = length;
// Handle memory allocation errors...
}
void libme_delete_string(struct libme_string* str)
{
// Check arguments...
free(str->buffer);
}
Use
struct libme_string str; // << different, not a pointer!
libme_create_string(&str, 1024);
// ...
libme_delete_string(&str);
Notes
string just a sample.
Method #2 is faster, isn't it?
Lastly, are there any good design guidelines for designing libraries written in C?

Personally, I would view the second version as less intuitive and more error prone.
If you're trying your hardest to encapsulate instantiation (which you should be doing anyway), then the first really is the only way to go — one step, done. The second version means that in order to have a fully initialized variable, you need to not only instantiate it, but you need to call a helper function on it immediately. That extra step is a bug waiting to happen.

Personally I prefer the first method. Agreed: it's a bit C++ like, but ...
thing_t *thing_new(...);
void thing_delete(thing_t *ptr);
I do think that all "size" or "count" members should be unsigned, preferably size_t.
Also: you last snippet tries to free() an automatic variable. That is a good reason not to use it.
EDIT:
There is (at least) a third way: return the entire object as a value. I don't particularly like the method, but it at least avoids the double allocation. It goes like this:
typedef struct {
StrLen length;
StrType type; /* type is not stored in the brainfile
**but recomputed on loading */
char *word;
} STRING;
STATIC STRING new_string(char *str, size_t len)
{
STRING this;
if (str) {
if (!len) len = strlen(str);
if (len) { this.word = malloc(len); memcpy(this.word, str, len); }
else { this.word = malloc(1); memset(this.word, 0, 1); }
this.length = len;
this.type = word_classify(this);
}
else {
this.word = NULL;
this.length = 0;
this.type = 0;
}
return this;
}
Typical usage goes like this:
if (*np == WORD_NIL) {
STRING this;
*np = dict->size++;
this = new_string(word.word, word.length);
dict->entry[*np].string = this;
dict->entry[*np].hash = hash_word(this);
}
(code inherited from megahal, reused in wakkerbot)
As I said, I don't like this method, but the struct assignment definitely has its advantages.

Why not factor the process into two functions, so you can use whichever you need:
struct libme_string * create_string();
void destroy_string(struct libme_string *);
struct libme_string * init_string(struct libme_string * str, unsigned int length);
struct limbe_string * deinit_string(struct libme_string * str);
Usage #1, all dynamic allocations:
struct libme_string * str = init_string(create_string(), 10);
destroy_string(deinit_string(str));
Usage #2, automatic outer struct:
struct libme_string str;
init_string(&str);
deinit_string(&str);
Make sure that the init functions return the pointer, so that you can compose the calls like I did.
If deinit() also sets the pointer to zero, then you could make destroy() call deinit() if the pointer is non-zero, though that breaks the symmetry a bit.

Related

Segmentation fault when strdupa void pointer

I'm fairly new to pointers, and void pointers is still black art to me.
In the following code I get a segfault when tmp->item = strdup(item);
I'm not sure how to fix.
int springmap_add(SpringMap *sm, char *key, void *item) {
SpringMap *tmp = sm;
.
.
.
while (tmp) {
if (!tmp->next) {
tmp->next = springmap_init();
tmp->next->key = strdup(key);
tmp->next->item = strdup(item); // Segfault here
return 1;
}
tmp = tmp->next;
}
return 0
}
int main(int argc, char* argv[]) {
char* key[ESTS] = {"alpha"};
void* ptr[ESTS] = {(void*)0xdeadbeef};
SpringMap* map = springmap_init();
for(int i = 0; i < TESTS; i++) {
int status = springmap_add(map, key[i], ptr[i]);
}
springmap_free(map);
return 0;
I'm not up to speed on void pointers.
The function name already tells: strdup composes of string duplicate, and it only is able to duplicate null-terminated C-strings (well, admittedly any data as long as it contains a null byte somewhere, though it would get cut off too early unless this null byte was the very last byte within the data).
void pointers in C have the unfortunate nature of implicitly converting to any other pointer type, happening in your code as well. However these pointers do not point to null-terminated C-strings, actually, they aren't even valid at all (most of most likely, at least)! Thus trying to read from them yields undefined behaviour.
So at first make sure that your void pointers point to valid memory. To use strdup they should point to C-strings, otherwise memcpy is the way to go, though you need to malloc storage space as target first. For both, you need the size of the object available, though. However you cannot get that back from the void pointer any more, thus you need yet another parameter.
You could write your own objdup function covering the duplication:
void* objdup(size_t size, void* object)
{
void* copy = malloc(size);
if(copy)
{
memcpy(copy, object, size);
}
return copy;
}
Still your pointers need to be valid! Some possible example might look like:
int main()
{
SomeDataType o1;
AnotherDataType o2;
AnotherDatatType* ptr = &o2; // create a valid pointer
// (could be done by malloc'ing memory, too)
void* c1 = objdup(sizeof(o1), &o1);
// ^ take the address of a REAL object!
if(c1)
{
void* c2 = objdup(sizeof(*o2), o2); // or via pointer to REAL object
if(c2)
{
// ...
free(c2);
}
free(c1);
}
return 0;
}

How to correctly free a structure returned from a function?

I'm new to C and trying to figure out how to dispose of the structures, references to which are returned from a function.
For example, this is roughly what I want to do.
typedef struct test_t{
char *test_c;
} test_t;
int testFunc(test_t** output){
test_t* testStruct = malloc(sizeof(testStruct));
char* buf = malloc(sizeof(char) * 5);
strcpy(buf, "test");
testStruct->test_c = buf;
*output = testStruct;
return 0;
}
int main() {
test_t* test;
testFunc(&test);
printf("%s\n",test->test_c);
free(test);
return 0;
}
So in main I get the test struct. After printf (assume that there is some code after wards) I no longer need it and want to deallocate it. But how to do it properly? Should I just deallocate test_c explicitly first? But what if it wasn't allocated?
A structure can be deallocated just like any other pointer. You however have to ensure that all its allocated members are freed before doing so (failing to do so would most likely result in a memory leak of the members of your structure).
typedef struct test_t{
char *test_c;
} test_t;
int testFunc(test_t** output){
test_t* testStruct = malloc(sizeof(testStruct));
char* buf = malloc(sizeof(char) * 5);
strcpy(buf, "test");
testStruct->test_c = buf;
*output = testStruct;
return 0;
}
int main() {
test_t* test;
testFunc(&test);
printf("%s\n",test->test_c);
free(test->test_c);
free(test);
return 0;
}
In case your structure doesn't allocate all of its elements, you can set their pointer to NULL, which once passed to free (3) would be equivalent to doing nothing.
But how to do it properly? Should I just deallocate test_c explicitly first? But what if it wasn't allocated?
Basic rule of thumb: if you write a function that allocates a resource, write a complementary one that deallocates it. So when applied to your example:
void testFree(test_t* toFree) {
free(toFree->test_c);
free(toFree);
}
... and then ...
printf("%s\n",test->test_c);
testFree(test);
If testFree is implemented and exposed along with testFunc, the callers don't need to know your implementation details. The functions themselves, being part of the same library, will make sure the invariants are maintained properly. Should you ever switch allocation schemes, no calling code needs to change. You would just modify testFree to go along with the new testFunc and re-link.
First, you'll need to free the memory you,ve allocated for the char in the struct given that you have initialized it. Otherwise, you'll get an error so before any free instruction you should check whether the pointer that holds the memory position for test_p you're trying to free isn't NULL. Besides, the free instruction should take *test as a parameter instead of test.
You should have a procedure which allocates and initializes an instance of test_t. In C++ or other object-oriented languages this would be a constructor. In C you have to roll your own - something similar to the following:
test_t *create_test_t(char *init_test_c)
{
test_t *tt;
tt = malloc(sizeof(test_t));
if(init_test_c != NULL)
{
tt->test_c = malloc(strlen(init_test_c)+1);
strcpy(tt->test_c, init_test_c);
}
else
tt->test_c = NULL;
}
You'll also want a function to get rid of a test_t instance correctly. Something like:
void destroy_test_t(test_t *tt, bool static)
{
free(tt->test_c);
if(!static)
free(tt);
}
The static parameter is included to control whether tt should or should not be free'd. Obviously you don't want to attempt to free a pointer to a static instance of test_t, in which case you'd pass TRUE for static. For dynamically-allocated instances of test_t, e.g. those created using the create_test_t procedure, you'd pass FALSE for static.
You then use these functions every time you need to create or destroy a test_t.
Best of luck.
Should I just deallocate test_c explicitly first?
Yes, you have to free test_c first, because, if you free test, you will lose the reference to test_c.
But what if it wasn't allocated?
As you are returning int from testFunc, you can use it as a state of the allocation of your structure (although, returning a pointer would be a better idea IMHO):
int testFunc(test_t** output){
test_t* testStruct = malloc(sizeof(testStruct));
if (testStruct == NULL)
/* testStruct allocation failure. */
return -1;
char* buf = malloc(sizeof(char) * 5);
if (buf == NULL) {
/* buf allocation failure. */
free(testStruct);
return -1;
}
strcpy(buf, "test");
testStruct->test_c = buf;
*output = testStruct;
return 0;
}
After that, you check testFunc failure:
/* Check for allocation failure. */
if (testFunc(&test) == -1) {
fprintf(stderr, "Allocation error");
exit(EXIT_FAILURE);
}
/* Allocation succeeded. */
printf("%s\n",test->test_c);
free(test->test_c);
free(test)

Issue copying string pointers contained in structs

So i have this struct which im using as a tree for a parser.
struct Expr{
struct Expr* a;
char* value;
struct Expr* b;
};
I initialize it with malloc like this.
Expr* initExp(){
Expr* ret;
ret = (Expr*)malloc(sizeof(Expr));
ret->a = (Expr*)malloc(sizeof(Expr));
ret->b = (Expr*)malloc(sizeof(Expr));
ret->value = (char*)malloc(sizeof(char));
ret->value = "18killstreak";
ret->a->value = "18killstreak";
ret->b->value = "18killstreak";
return ret;
}
I have written more here in the function than i needed to in the process of debugging so far and for printing the tree.
So I am trying to copy an Expr* a-> value into a Expr* value like this.
strcpy(temp2->value,ret->a->value);
While the values are "18killstreak" and "x" respectively.
But my program crashes at this line and I have tried many other tactics at this point.
The problem is that you're not managing memeory for your strings, so you can't just use strcpy. For example, when you have:
ret->value = (char*)malloc(sizeof(char));
ret->value = "18killstreak";
this allocats space for a 0-length string (just a NUL), and then throws it away (the memory leaks), overwriting the allocated pointer with a pointer to a static constant string "18Killstreak". When you later try to overwrite the static constant string (with strcpy) you get a crash.
So to do it correctly, you need to allocate and manage memory for the strings. The easiest way to do that is to have each struct Expr own the memory for the string and use strdup/free appropriately to alloc/copy/free that memory. So your init function becomes:
Expr* ret;
ret = (Expr*)malloc(sizeof(Expr));
ret->a = (Expr*)malloc(sizeof(Expr));
ret->b = (Expr*)malloc(sizeof(Expr));
ret->value = strdup("18killstreak");
ret->a->value = strdup("18killstreak");
ret->b->value = strdup("18killstreak");
Later when you want to replace the value of a struct, you do:
free(temp2->value);
temp2->value = strdup(ret->a->value);
and when you want to free an Expr, you need to also (first) free the value:
free(exp->value);
free(exp);
Now one isuue with this is that strdup is not a standard C function -- it's a POSIX function. So it is available on POSIX systems (such as Linux or OSX), but not on non-POSIX systems. So you may need to define it yourself:
char *strdup(const char *str) {
char *rv = malloc(strlen(str) + 1);
if (rv) strcpy(rv, str);
return rv;
}

Freeing memory, functions

I am trying to free some memory that I allocated in one functions in another function. An example of this would be:
MusicRec * createRecord(char * title, char * artist, double fileSize, int length, char theType)
{
MusicRec * newRecord;
MusicRec * next;
newRecord = malloc(sizeof(MusicRec));
newRecord->title = malloc(sizeof(char)*(strlen(title))+1);
strcpy(newRecord->title, title);
newRecord->artist = malloc(sizeof(char)*(strlen(artist))+1);
strcpy(newRecord->artist, artist);
newRecord->sizeInKB = fileSize;
newRecord->lengthInSeconds = length;
newRecord->type = theType;
newRecord->next = NULL;
next = NULL;
return(next);
}
I have malloced memory in that function, but now i am trying to free this malloced memory in a different function such as my main function. How would i do this?
Just use the corresponding deallocation function free() Remember you cannot use already deallocated memory at all.
Some points to consider:
Better change how you allocate memory, so you can more easily change the type:
Was: newRecord = malloc(sizeof(MusicRec));
Should be: newRecord = malloc(sizeof *newRecord);
Consider defining some helper functions for things you often do. Example (this function is often actually already defined):
Was: newRecord->title = malloc(sizeof(char)*(strlen(title))+1);strcpy(newRecord->title, title);
Should be: newRecord->title = strdup(title);
Never use sizeof(char): It looks illiterate, because you are literally asking: How many char's do I need to save one char?
For cases it's not defined:
char* strdup(const char* str) {
size_t len = strlen(str) + 1;
char* ret = malloc(len);
memcpy(ret, str, len);
return ret;
}
If you have passed that variable as reference from another function then you can free that variable from that function using free() function; otherwise you can not free that variable from another function if you have passed by value.

how to create a dynamic array of structs in C

I want to send a struct of symbol from one function to other functions, and i want to create an array that every cell will point to a different values of the following struct:
typedef struct symbol_def
{
char* sym_name;
char* sym_type;
unsigned short sym_address;
char sym_is_ext;
}symbol;
I'm trying to run this code:
//function-1
void compile_input_file(char* input)
{
symbol* curr_symbol;
//Intalize curr_symbol struct
curr_symbol = (symbol*)malloc(sizeof(symbol));
//memset((void)curr_symbol, 0, sizeof(symbol));
parse_command(line, &parser, curr_symbol, &index);
}
//function-2
void parse_command(char* line, parse_params* parser, symbol* curr_symbol, int* index)
{
sym = symbol_table_create(curr_symbol, "directive", sym_label, '0', index);
}
//function-3
symbol* symbol_table_create(symbol* curr_symbol,char* s_type, char* label, char is_ext, int* index)
{
int temp = *index;
curr_symbol = (symbol*)realloc(curr_symbol,sizeof(symbol*)*(temp+1));
curr_symbol[temp].sym_type = s_type;
curr_symbol[temp].sym_name = label;
curr_symbol[temp].sym_address = 0;
curr_symbol[temp].sym_is_ext = is_ext;
temp++;
*index = temp;
return curr_symbol;
}
The problem is that the curr_symbol gets override all the time.
my purpose is to build a table of symbols, that in every iteration on the code i'll add another cell to the array
any ideas?
There is a problem, with the realloc It should be curr_symbol = (symbol*)realloc(curr_symbol,sizeof(symbol)*(temp+1)); You were actually allocating it sizeof pointer which is 4 Bytes.
A Piece of Advice Realloc is a costly operation you should use it only if necessary and not on every instance
you could malloc in function3 instead of function1. If you do so you dont even need to pass the pointer via function2.
or else put a check to see if realloc is really necessary or not. Eg:- Check if the pointer is allocated memory. if(ptr!=null){ //realloc } This can work as a checking case too.
Best of Luck. :)

Resources