|
|
| Using 'free' on garbage values |
|
OnlineCop
Member #7,919
October 2006
|
I have this C structure: 1typedef struct
2{
3 char *array;
4 unsigned int capacity;
5 unsigned int size;
6} s_string;
To clear it, I call this function: Assuming that I create a new object: 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
|
|
bamccaig
Member #7,536
July 2006
|
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. -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
|
Arthur Kalliokoski
Second in Command
February 2005
|
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
|
Arthur Kalliokoski said: 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: 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). -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
|
OnlineCop
Member #7,919
October 2006
|
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? 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)... 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
|
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" |
|
OnlineCop
Member #7,919
October 2006
|
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: 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: 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
|
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" |
|
OnlineCop
Member #7,919
October 2006
|
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.
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}
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 */
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
|
So you'll never use a s_string *str ? "Code is like shit - it only smells if it is not yours" |
|
OnlineCop
Member #7,919
October 2006
|
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
|
In that case everything seems ok to me :-) "Code is like shit - it only smells if it is not yours" |
|
bamccaig
Member #7,536
July 2006
|
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): 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? -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
|
OnlineCop
Member #7,919
October 2006
|
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
|
Instead of manually setting to 0/NULL all the items in the init function, just use memset. Lots easier -- |
|
Kitty Cat
Member #2,815
October 2002
|
Thomas Fjellstrom said: 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. -- |
|
OnlineCop
Member #7,919
October 2006
|
Kitty Cat 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)?
|
|
Thomas Fjellstrom
Member #476
June 2000
|
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 -- |
|
bamccaig
Member #7,536
July 2006
|
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. -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
|
Kitty Cat
Member #2,815
October 2002
|
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)? 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. -- |
|
bamccaig
Member #7,536
July 2006
|
I've added a branch to libbam to work on a UTF-8 compatible string type. -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
|
OnlineCop
Member #7,919
October 2006
|
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
|
|
bamccaig
Member #7,536
July 2006
|
OnlineCop said:
bamccaig: looks like your src/bam_string.c is a little bare
Yeah, it's a WIP[1]. References
-- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
|
|