Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Using 'free' on garbage values

This thread is locked; no one can reply to it. rss feed Print
Using 'free' on garbage values
OnlineCop
Member #7,919
October 2006
avatar

I have this C structure:

cstring.h#SelectExpand
1typedef struct 2{ 3 char *array; 4 unsigned int capacity; 5 unsigned int size; 6} s_string;

To clear it, I call this function:

cstring.c#SelectExpand
1void free_string (s_string *which_array) 2{ 3 assert (which_array && "which_array == NULL"); 4 5 if (which_array->array) 6 free (which_array->array); 7 8 which_array->capacity = 0; 9 which_array->size = 0; 10}

Assuming that I create a new object:

main.c#SelectExpand
1#include "cstring.h" 2 3int main() 4{ 5 s_string my_string; 6 free_string(&my_string); 7 8 ... 9 return 0; 10}

What will happen to the call to free() if the garbage found within my_string (more specifically, my_string->array) is non-NULL or (even worse :o) just happens to be pointing to some memory location that I had actually used malloc() on so it's a "valid" allocation address (ref), but not one that I actually want to free?

bamccaig
Member #7,536
July 2006
avatar

Obviously, if the value points to memory that you haven't allocated the OS will terminate your program (I just tried with a random integer and it segfaulted). If it points to memory that you have allocated, but have no intent to free, your program will segfault later on if you dereference it.

You just need to define an API to use with the string. Either require string_init on stack allocated strings or use string_create to allocate heap allocated strings, both of which would act like a constructor and set the structures values to valid values.

Arthur Kalliokoski
Second in Command
February 2005
avatar

bamccaig said:

use string_create to allocate heap allocated strings, both of which would act like a constructor and set the structures values to valid values

You're depending on malloc() to zero out the memory? (for security reasons). This 64 bit linux I'm using doesn't do that anymore for some reason. The calloc() function still works as expected. Or is string_create some C++ thing that does it?

[EDIT]

nevermind, I just woke up. I must have been thinking of allocating an array of pointers.

They all watch too much MSNBC... they get ideas.

bamccaig
Member #7,536
July 2006
avatar

You're depending on malloc() to zero out the memory?

Me? I was relying on my own API function to do it... Perhaps it should be called s_string_create instead:

#SelectExpand
1s_string * s_string_create(void) 2{ 3 s_string * s = (s_string *)malloc(sizeof(s_string)); 4 5 if(!s) 6 return 0; 7 8 s->array = 0; 9 s->capacity = 0; 10 s->size = 0; 11 12 return s; 13} 14 15s_string * s_string_create_cstr(const char * const initval) 16{ 17 s_string * s = 0; 18 19 if(!initval) 20 return s_string_create(); 21 22 s = (s_string *)malloc(sizeof(s_string)); 23 24 if(!s) 25 return 0; 26 27 s->capacity = sizeof(strlen(initval)); 28 s->size = capacity; 29 s->array = (char *)malloc(s->capacity + 1); 30 31 if(!s->array) 32 { 33 free(s); 34 return 0; 35 } 36 37 strncpy(s->array, initval, s->capacity); 38 s->array[s->size + 1] = '\0'; 39 40 return s; 41}

I would also write my own API functions for access, manipulation, and destruction to ensure that the structure was always valid (assuming no bugs in the API).

OnlineCop
Member #7,919
October 2006
avatar

So have one function that 0's everything, another to 0 everything once there have already been some sort of malloc/calloc/realloc used to assign memory on the heap?

cstring.c#SelectExpand
1void s_string_create(s_string *which_array) 2{ 3 assert(which_array && "which_array == NULL"); 4 5 which_array->capacity = 0; 6 which_array->size = 0; 7 which_array->array = 0; // NULL 8}

...then (unchanged from above)...

cstring.c#SelectExpand
1void free_string (s_string *which_array) 2{ 3 assert (which_array && "which_array == NULL"); 4 5 if (which_array->array) 6 free (which_array->array); 7 8 which_array->capacity = 0; 9 which_array->size = 0; 10}

which is only used after I've used up the string and want to deallocate memory before leaving a function or whatever.

bamccaig said:

I would also write my own API functions for access, manipulation, and destruction to ensure that the structure was always valid (assuming no bugs in the API).

Doing this. This is actually WHY I'm writing these functions: everything is currently "let's directly access/manipulate/destroy the strings." I'm tired of everyone doing it their "own way" which can lead to hard-to-debug bugs.

GullRaDriel
Member #3,861
September 2003
avatar

malloc isn't guaranteed to return you a zeroed array.

Test at work have shown that until you actually write in the allocated array, the OS is likely to just create an entry in the the memory pool without reserving it.

For that purpose you should use calloc.

Plus strncpy \0 to a char array is just silly. memcpy, or directly calloc it.

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

OnlineCop
Member #7,919
October 2006
avatar

I don't care whether the array is 0'd or not. In fact, if the char* array is allocated to some huge value, it's faster to simply allocate the memory with malloc and keep track of string length with size (which is actually what I'm doing), than to calloc it and wait while the contents are 0'd out.

Another option I could use is:

main.c#SelectExpand
1int main() 2{ 3 s_string my_string; 4 my_string.array = 0; // NULL 5 free_string(&my_string); 6 7 ... 8 return 0; 9}

This requires that I remember to always 0-out the array before calling free_string(), but it reduces redundant code:

cstring.c#SelectExpand
1/*! \brief Free the string, deallocate memory 2 * 3 * Clear the array, setting both the capacity and size to 0. This frees any 4 * previously-allocated 'array' memory. Not to be used for newly-created 5 * objects as 'array' can be pointing to garbage values instead of NULL. 6 */ 7void free_string (s_string *which_array) 8{ 9 assert (which_array && "which_array == NULL"); 10 11 if (which_array->array) 12 free (which_array->array); 13 14 which_array->array = 0; // NULL 15 which_array->capacity = 0; 16 which_array->size = 0; 17} 18 19 20 21/*! \brief Initialize new s_string objects 22 * 23 * Set capacity, size, and array to 0's to remove garbage memory values. Do 24 * not use this in place of \sa free_string, where the array has already been 25 * allocated, else it will cause a memory leak. 26 */
27void init_string (s_string *which_array)
28{ 29 assert (which_array && "which_array == NULL"); 30 31 which_array->array = 0; // NULL 32 which_array->capacity = 0; 33 which_array->size = 0; 34}

GullRaDriel
Member #3,861
September 2003
avatar

free_string should also free the given container. You're not gonna use static only s_string declaration, aren't you ?

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

OnlineCop
Member #7,919
October 2006
avatar

The s_string object is being used for a reusable string location, similar to std::string. If you want to see the full code and the test app for it, it's in the Spoiler.

main.c#SelectExpand
1#include <stdio.h> 2 3#include "cstrings.h" 4 5 6int main(int argc, char** argv) 7{ 8 s_string sstring; 9 init_string(&sstring); 10 11 set_text(&sstring, "Hi"); 12 printf("- c(%u), s(%u), \"%s\"\n", sstring.capacity, sstring.size, sstring.array); 13 14 set_text(&sstring, "Hello"); 15 printf("- c(%u), s(%u), \"%s\"\n", sstring.capacity, sstring.size, sstring.array); 16 17 set_text(&sstring, "This text isn't long, but it ain't short neither!"); 18 printf("- c(%u), s(%u), \"%s\"\n", sstring.capacity, sstring.size, sstring.array); 19 20 set_text(&sstring, "Hi again"); 21 printf("- c(%u), s(%u), \"%s\"\n", sstring.capacity, sstring.size, sstring.array); 22 23 // Should shrink to next power-of-two 24 if (shrink_text(&sstring)) 25 printf("(shrunk)\n- c(%u), s(%u), \"%s\"\n", sstring.capacity, sstring.size, sstring.array); 26 27 // Should shrink to size+1 28 if (shrink_text(&sstring)) 29 printf("(shrunk)\n- c(%u), s(%u), \"%s\"\n", sstring.capacity, sstring.size, sstring.array); 30 31 // Should have absolutely NO effect 32 if (shrink_text(&sstring)) 33 printf("- c(%u), s(%u), \"%s\"\n", sstring.capacity, sstring.size, sstring.array); 34 35 clear_string(&sstring); 36 printf("(cleared)\n- c(%u), s(%u), \"%s\"\n", sstring.capacity, sstring.size, sstring.array); 37 38 set_text(&sstring, "1234567890ABCDE"); 39 printf("- c(%u), s(%u), \"%s\"\n", sstring.capacity, sstring.size, sstring.array); 40 41 if (shrink_text(&sstring)) 42 printf("(shrunk)\n- c(%u), s(%u), \"%s\"\n", sstring.capacity, sstring.size, sstring.array); 43 44 free_string(&sstring); 45 return 0; 46}

cstrings.h#SelectExpand
1#ifndef __CSTRINGS_H 2#define __CSTRINGS_H 1 3 4 5/*! \file 6 * \brief Adding further support of C-style strings 7 * \author OC 8 * \date 20100304 9 */ 10 11 12typedef struct 13{ 14 char *array; 15 unsigned int capacity; 16 unsigned int size; 17} s_string; 18 19 20void clear_string (s_string *); 21void free_string (s_string *); 22void init_string (s_string *); 23int prealloc_string (s_string *, unsigned int); 24int set_text (s_string *, const char *); 25int shrink_text (s_string *); 26 27 28 29#endif /* __CSTRINGS_H */

cstrings.c#SelectExpand
1/*! \file 2 * \brief Handle s_string allocation/reuse/destruction 3 * \author OC 4 * \date 20100304 5 */ 6 7#include <assert.h> 8#include <ctype.h> 9#include <math.h> 10#include <stdio.h> 11#include <stdlib.h> 12#include <string.h> 13 14#include "cstrings.h" 15 16 17/*! \brief Clear the string of its contents 18 * 19 * This function does not free the allocated memory; instead, it resets the 20 * size to 0 and clears the array with '\0' values (or at least, the first 21 * one is set to '\0'). Capacity remains the same so the object can be reused 22 * without needing to reallocate memory for it. 23 * 24 * To free the memory, call the \sa free_string function. 25 */ 26void clear_string (s_string *which_array) 27{ 28 assert(which_array && "which_array == NULL"); 29 30 if (which_array->capacity > 0) 31 which_array->array[0] = '\0'; 32 which_array->size = 0; 33} 34 35 36 37/*! \brief Free the string, deallocate memory 38 * 39 * Clear the array, setting both the capacity and size to 0. This frees any 40 * previously-allocated 'array' memory. Not to be used for newly-created 41 * objects as 'array' can be pointing to garbage values instead of NULL. 42 */ 43void free_string (s_string *which_array) 44{ 45 assert (which_array && "which_array == NULL"); 46 47 if (which_array->array) 48 free (which_array->array); 49 50 which_array->array = 0; // NULL 51 which_array->capacity = 0; 52 which_array->size = 0; 53} 54 55 56 57/*! \brief Initialize new s_string objects 58 * 59 * Set capacity, size, and array to 0's to remove garbage memory values. Do 60 * not use this in place of \sa free_string, where the array has already been 61 * allocated, else it will cause a memory leak. 62 */ 63void init_string (s_string *which_array) 64{ 65 assert (which_array && "which_array == NULL"); 66 67 which_array->array = 0; // NULL 68 which_array->capacity = 0; 69 which_array->size = 0; 70} 71 72 73 74/*! \brief Preallocate enough memory for string usage 75 * 76 * If the size of the string is known before-hand, it vastly simplifies adding 77 * text to the string. Otherwise, multiple reallocations are necessary and 78 * wasteful. 79 * This produces a capacity to the next power-of-two, not to `new_capacity'. 80 * 81 * \param which_array - Smart array containing char* array to preallocate 82 * \param new_capacity - Number of elements to preallocate (min: 8) 83 * \returns 0 if allocation failed 84 * \returns 1 if allocation succeeded 85 */ 86int prealloc_string (s_string *which_array, unsigned int new_capacity) 87{ 88 unsigned int next_power_of_two; 89 assert (which_array && "which_array == NULL"); 90 91 if (new_capacity < 8) 92 new_capacity = 8; 93 94 /* If the current capacity is already larger than 'new_capacity', there is 95 * no reason to resize the array. Only resize it if not. 96 */ 97 if (which_array->capacity < new_capacity) { 98 next_power_of_two = (unsigned int) pow (2, ceil (log2 (new_capacity))); 99 if (which_array->capacity == 0) 100 which_array->array = malloc (next_power_of_two * sizeof (char)); 101 else 102 which_array->array = realloc (which_array->array, next_power_of_two * sizeof (char)); 103 104 assert (which_array->array && "Could not preallocate necessary space!"); 105 which_array->capacity = next_power_of_two; 106 } 107 108 return 1; 109} 110 111 112 113/*! \brief Assign the text to the s_string object. 114 * 115 * Allocate at least the amount of space needed for the new text to fit in the 116 * array; memory is allocated in 2^n blocks, even if not all blocks are used. 117 * 118 * \param which_array - Smart array containing char* array to fill 119 * \param new_text - Text string to add to the array 120 * \returns 0 if allocation or text assignment failed 121 * \returns 1 on success 122 */ 123int set_text (s_string *which_array, const char *new_text) 124{ 125 unsigned int i; 126 unsigned int next_power_of_two; 127 unsigned int size; 128 assert (which_array && "which_array == NULL"); 129 assert (new_text && "new_text == NULL"); 130 131 size = strlen (new_text); 132 if (!which_array->array || size + 1 > which_array->capacity) // +1 for the '\0' at the end 133 prealloc_string (which_array, size + 1); 134 135 if (strncpy (which_array->array, new_text, size) == 0) // NULL 136 return 0; 137 138 which_array->array[size] = '\0'; 139 which_array->size = size; 140 return 1; 141} 142 143 144 145/*! \brief Resize the char* array to the smallest possible amount. 146 * 147 * If an array's capacity grows too large and needs to be trimmed, this will 148 * reduce its size: 149 * 1) If the capacity can be shrunk to a smaller next-power-of-two, it will be 150 * 2) Otherwise, the capacity will be shrunk to size+1 (size + trailing '\0') 151 * 152 * This is useful for situations like: 153 * before[] = "This is a very long string of text."; (35 characters + '\0') 154 * after[] = "Smaller."; (8 characters + '\0') 155 * 156 * The before[] string takes up 36 characters with a capacity of 64. 157 * The after[] string takes up 9 characters with a capacity of 16. 158 * 159 * Calling this function the first time will shrink the capacity from 64 to 16 160 * and the second call will shrink it from 16 to 10 (9 + '\0'). 161 * 162 * \param which_array - Smart array containing char* array to reallocate 163 * \returns 0 if array not resized (already as small as it can get) 164 * \returns 1 if array shrunk 165 */ 166int shrink_text (s_string *which_array) 167{ 168 unsigned int next_power_of_two; 169 unsigned int new_capacity; 170 char *temp_array; 171 assert (which_array && "which_array == NULL"); 172 173 if (which_array->capacity == which_array->size + 1) 174 return 0; // Array is already as small as it can get 175 176 next_power_of_two = (unsigned int) pow (2, ceil (log2 (which_array->size + 1))); 177 if (which_array->capacity == next_power_of_two) 178 new_capacity = which_array->size + 1; // Shrink to exact size + '\0' 179 else 180 new_capacity = next_power_of_two; // Shrink to next power-of-two 181 182 temp_array = malloc (new_capacity); 183 strncpy (temp_array, which_array->array, which_array->size); 184 temp_array[which_array->size] = '\0'; // append a trailing '\0' for safety 185 free (which_array->array); 186 187 which_array->array = temp_array; 188 which_array->capacity = new_capacity; 189 190 return 1; 191}

I don't allocate and free the s_string container, since I want it to be more-or-less persistent. When a long string is given, it should expand the array's size as needed. But when a shorter string is given, instead of freeing the memory, it simply replaces the text and sets the size to fit it.

GullRaDriel
Member #3,861
September 2003
avatar

So you'll never use a s_string *str ?

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

OnlineCop
Member #7,919
October 2006
avatar

Not typically, no. If suppose I would use them if I'm going to have an array of text, similar to std::vector< std::string >, but since it only needs to allocate 2 unsigned int's and one pointer on the stack, I'm not too worried about putting it on the heap at this point. Only the s_string.array is ever allocated on the heap.

GullRaDriel
Member #3,861
September 2003
avatar

In that case everything seems ok to me :-)

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

bamccaig
Member #7,536
July 2006
avatar

I've been wanting to write my own string API for C and C++ also (to make strings convenient, like in modern languages). I might add the following to what you already have (I would also add the type_ prefix to what you have to avoid name collisions):

#SelectExpand
1char * s_string_as_cstr (const s_string * const); 2s_string * s_string_concat (s_string * const, 3 const s_string * const); 4s_string * s_string_concat_cstr (s_string * const, 5 const char * const); 6s_string * s_string_copy (const s_string * const); 7int s_string_compare (const s_string * const, 8 const s_string * const); 9int s_string_compare_cstr (const s_string * const, 10 const char * const); 11int s_string_contains (const s_string * const, 12 const s_string * const); 13int s_string_contains_cstr (const s_string * const, 14 const char * const); 15int s_string_ends_with (const s_string * const, 16 const s_string * const); 17int s_string_ends_with_cstr (const s_string * const, 18 const char * const); 19int s_string_equals (const s_string * const, 20 const s_string * const); 21int s_string_equals_cstr (const s_string * const, 22 const char * const); 23s_string * s_string_from_cstr (s_string * const, 24 const char * const); 25char s_string_getchar (const s_string * const, 26 const int); 27int s_string_index_of (const s_string * const, 28 const s_string * const); 29int s_string_index_of_cstr (const s_string * const, 30 const char * const); 31int s_string_is_empty (const s_string * const); 32s_string * s_string_join (const s_string * const * const, 33 const s_string * const); 34s_string * s_string_join_cstr (const s_string * const * const, 35 const char * const); 36int s_string_last_index_of (const s_string * const, 37 const s_string * const); 38int s_string_last_index_of_cstr (const s_string * const, 39 const char * const); 40int s_string_length (const s_string * const); 41s_string * s_string_ltrim (s_string * const); 42int s_string_is_null_or_empty (const s_string * const); 43int s_string_is_null_or_whitespace (const s_string * const); 44s_string * s_string_padleft (s_string * const, 45 const int, 46 const char); 47s_string * s_string_padright (s_string * const, 48 const int, 49 const char); 50s_string * s_string_remove (s_string * const, 51 const int, 52 const int); 53s_string * s_string_replace (s_string * const, 54 const s_string * const); 55s_string * s_string_replace_cstr (s_string * const, 56 const char * const); 57s_string * s_string_rtrim (s_string * const); 58int s_string_printf (const s_string * const, 59 ...); 60s_string ** s_string_split (const s_string * const, 61 const s_string * const, 62 int * const); 63s_string ** s_string_split_cstr (const s_string * const, 64 const char * const, 65 int * const); 66s_string * s_string_setchar (s_string * const, 67 const int, 68 const char); 69int s_string_sprintf (s_string * const, 70 const s_string * const, 71 ...); 72int s_string_sprintf_cstr (s_string * const, 73 const s_string * const, 74 ...); 75int s_string_starts_with (const s_string * const, 76 const s_string * const); 77int s_string_starts_with_cstr (const s_string * const, 78 const char * const); 79s_string * s_string_substr (const s_string * const, 80 const int, 81 const int); 82s_string * s_string_tolower (s_string * const); 83s_string * s_string_toupper (s_string * const); 84s_string * s_string_trim (s_string * const); 85int s_string_vprintf (const s_string * const, 86 va_list); 87int s_string_vsprintf (s_string * const, 88 const s_string * const, 89 va_list); 90int s_string_vsprintf_cstr (s_string * const, 91 const char * const, 92 va_list);

Too much? ???

OnlineCop
Member #7,919
October 2006
avatar

bamccaig, scrolling through your list quickly, I can see an immediate use for concatenation. A lot of the others, though, would be useful mainly for a full-fledged API like you're suggesting, since it would help protect the data members (like C++'s private: and protected: keywords do).

Using printf or its variants could be done directly on the array member of the item with what I'm looking at, as data protection isn't as big of a concern for me.

I don't know if I'll need any special handling for UTF8/UTF16 or Unicode formats, so if I find that things are breaking, I may have to change my habits. Using the "gettext.h" library, a lot of the strings I'm passing into these functions will be converted to the appropriate type, though I'm not sure if finding all of those "0x00"'s throughout will mean a rewrite to this code, or if it'll "just work". I may have to replace "strlen()" with a unicode-aware variant, perhaps?

Thomas Fjellstrom
Member #476
June 2000
avatar

Instead of manually setting to 0/NULL all the items in the init function, just use memset. Lots easier ;D

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Kitty Cat
Member #2,815
October 2002
avatar

Instead of manually setting to 0/NULL all the items in the init function, just use memset. Lots easier

May as well use calloc in that case, then. Even easier. Just be careful because NULL isn't guaranteed to have a 0'd out bit pattern.

And FYI, freeing NULL is valid, so it's useless to check the pointer for non-NULL before calling free.

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

OnlineCop
Member #7,919
October 2006
avatar

  1. I don't want to 0 out all of the memory within the array when I'm freeing it: only the pointer needs to be set to 0/NULL.

  2. The string arrays don't necessarily <i>need</b> to be 0'd out: if I store my size variable (a lot like std::string), what's the point of memset/calloc all the remaining array elements to 0? I loop from 0..array.size; nothing more, therefore, no out-of-bounds (and if I'm dumb enough to TRY to access out-of-bounds data, I deserve the resulting SEGFAULT).

Kitty Cat said:

And FYI, freeing NULL is valid, so it's useless to check the pointer for non-NULL before calling free.

True. But what's faster: testing a register for 0, or calling a function which will just return immediately (because it runs the same "if NULL" test)? 8-)

Thomas Fjellstrom
Member #476
June 2000
avatar

Kitty Cat said:

May as well use calloc in that case, then. Even easier. Just be careful because NULL isn't guaranteed to have a 0'd out bit pattern.

You can't calloc a statically allocated struct :P

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

bamccaig
Member #7,536
July 2006
avatar

OnlineCop said:

bamccaig, scrolling through your list quickly, I can see an immediate use for concatenation. A lot of the others, though, would be useful mainly for a full-fledged API like you're suggesting, since it would help protect the data members (like C++'s private: and protected: keywords do).

Using printf or its variants could be done directly on the array member of the item with what I'm looking at, as data protection isn't as big of a concern for me.

I just think that the advantage you get from relying on accessors is beneficial over the minor performance gain you get by directly accessing the member. Of course, it's easy to manually access it, but humans make mistakes and eventually it can lead to a hard to track down bug. I'd rather go with safe/defensive programming until a particular bottleneck has been identified with an actual tool, at which point optimizations can be made to that particular part of code. Direct access is still possible for when you need it.

OnlineCop said:

I don't know if I'll need any special handling for UTF8/UTF16 or Unicode formats, so if I find that things are breaking, I may have to change my habits. Using the "gettext.h" library, a lot of the strings I'm passing into these functions will be converted to the appropriate type, though I'm not sure if finding all of those "0x00"'s throughout will mean a rewrite to this code, or if it'll "just work". I may have to replace "strlen()" with a unicode-aware variant, perhaps?

Now that you mention it, I think it would be nice to have an API for manipulating UTF-8 strings in C and C++. There'd be a minor performance penalty, but overall the flexibility of UTF-8 would be very convenient to have. I think if I ever do tackle a string data type (in C and/or C++) I'd want it to be UTF-8 based.

Kitty Cat
Member #2,815
October 2002
avatar

OnlineCop said:

True. But what's faster: testing a register for 0, or calling a function which will just return immediately (because it runs the same "if NULL" test)? 8-)

Depends if the variable's already in a register or not, whether it's in cache or not, and how likely it is for the test to fail. While the check could avoid a quick function call, it could just as easily incur an extra check (and branches aren't cheap).

Not that you should be allocating and freeing in speed-sensitive code, so it shouldn't matter much either way. In that case, I'd simply ask why duplicate what the standard already guarantees for you.

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

bamccaig
Member #7,536
July 2006
avatar

OnlineCop
Member #7,919
October 2006
avatar

Actually, why not just use what's already been done in Allegro?

I wanted to pull some sort of printf or sprintf functionality, and from the 4.2 (and 4.4) sources, I found that in src/text.c, the textprintf() function just calls uvszprintf() from within the src/unicode.c file, and that calls its own helper files, and so on and so forth.

The only "problem" or "limitation" I saw with what they did with it is that the character buffer has to be allocated ahead of time (so doing something like "char buf[512];" which you pass in as one of the arguments to uvszprintf, whereas I would want to actually have that buffer grow to fit the situation more dynamically (like a std::string would allow).

But if you're going to be be using the Allegro library anyway, I guess it's pointless to reinvent the wheel: just use what's already been done and tested (cross-platform, and bugs worked out by a whole community, to boot!).

So now I'm adding a new function that creates that "buf[]" on the stack (maybe I can still do it on the heap... ::ponders:: ), and after it's been filled by the formatted string, just call set_text() to actually set the string.

A lot of running around and hoop-jumping, but it'll be faster to continue on with the rest of the programming and come back to this and "perfect" the guts at a later time. After all, that is the whole reason for OOP's code-hiding...

EDIT: bamccaig: looks like your src/bam_string.c is a little bare :P The header file has a LOT more to look at ;)

bamccaig
Member #7,536
July 2006
avatar

OnlineCop said:

bamccaig: looks like your src/bam_string.c is a little bare :P The header file has a LOT more to look at ;)

Yeah, it's a WIP[1]. :P I'm sort of in the mood to approach the source tonight, but I expect I'll hit some crippling road block[2] long before it's working and then put it off for a few months. :P Hopefully that doesn't happen. I'm sure there's a lot to learn by implementing a UTF-8 string. Unicode has interested me for a long time now and it's nice in languages like C# where you just automatically have support. It would be sweet to have a similar luxury in C and C++.

References

  1. Work in planning.
  2. Like sleep... :-X
Go to: