我正在玩弄字符串的「胖指針」想法。基本上我有頭結構容量和長度信息。我分配預設長度的字符,然後將指針返回到第一個字符。當我想要標題信息時,我會減去'sizeof'標題。Realloc在字符串調整大小功能中失敗
所有功能都正常工作,我希望他們除了調整大小功能的方式:
typedef uint8_t* utf8;
/*
* Resize string
*/
bool string_resize(utf8 *str, size_t room) {
utf8* p = str;
struct string_header *hdr = (string_header_t *) (*p - sizeof(string_header_t));
size_t cap = hdr->capacity;
size_t len = hdr->length;
/* Backup the current capacity if the process fails */
size_t bck = cap;
if (len + room <= cap) {
//printf("::hit\n");
return true;
}
cap = len + room;
if (cap < MAX_PREALLOC) {
cap *= 2;
} else {
cap += MAX_PREALLOC;
}
hdr->capacity = cap;
void * new = realloc(hdr, sizeof(string_header_t) + cap + 1);
if (new == NULL) {
hdr->capacity = bck;
return false;
}
*str = (utf8) new + sizeof(string_header_t);
/* Remove garbage if there is any after the string content */
memset(*str+len, 0, cap-len + 1);
return true;
}
Valgrind的返回,我在存儲器中讀取的錯誤不是由malloc的分配(試圖訪問新時總是會發生字符串的一部分)。
正如你所看到的我使用(沒有typedef)uint8_t **所以我應該傳遞正確的指針指向函數的指針,然後改變它。
任何幫助非常感謝。
[更新1]字符串處理的上下文附加功能:
typedef struct string_header {
size_t capacity;
size_t length;
} string_header_t;
/*
* Allocate the string with the prefered length.
*/
utf8 string_alloc(size_t len) {
struct string_header *hdr = calloc(1, sizeof(string_header_t) + sizeof(uint8_t) * len);
assert(hdr);
hdr->capacity = len;
hdr->length = 0;
return ((utf8) hdr) + sizeof(string_header_t);
}
/*
* Allocate the new string with the initial default capacity.
*/
utf8 string_new() {
return string_alloc(INITIAL_CAPACITY);
}
/*
* Delete the string.
*/
void string_dealloc(utf8 self) {
if (self == NULL)
return;
string_header_t *hdr = (string_header_t *) (self - sizeof(string_header_t));
free(hdr);
}
static inline void string_push(utf8 s, char c) {
string_header_t* hdr = (string_header_t *) (s - sizeof(string_header_t));
//*(s + hdr->length++) = (uint8_t) c;
size_t len = hdr->length++;
s[len] = c;
}
bool string_append_char(utf8 str, char c) {
if (string_resize(&str, 1) != ARDP_SUCCESS)
return ARDP_FAILURE;
string_push(str, c);
return ARDP_SUCCESS;
}
bool string_append_utf8(utf8 s, int cp) {
if (cp < 0 or cp > 0x10ffff) {
return false;
}
else if (cp < 0x80) {
return string_append_char(s, cp & 0x7F);
}
else if (cp < 0x800) {
if (string_resize(&s, 2) isnt ARDP_SUCCESS)
return false;
string_push(s, 0xC0 | ((cp >> 6) & 0x1F));
string_push(s, 0x80 | (cp & 0x3F));
}
else if (cp < 0x10000) {
if (string_resize(&s, 3) isnt ARDP_SUCCESS)
return false;
string_push(s, 0xE0 | ((cp >> 12) & 0xF));
string_push(s, 0x80 | ((cp >> 6) & 0x3F));
string_push(s, 0x80 | (cp & 0x3F));
}
else {
if (string_resize(&s, 4) isnt ARDP_SUCCESS)
return false;
string_push(s, 0xF0 | ((cp >> 18) & 0x7));
string_push(s, 0x80 | ((cp >> 12) & 0x3F));
string_push(s, 0x80 | ((cp >> 6) & 0x3F));
string_push(s, 0x80 | (cp & 0x3F));
}
return true;
}
bool string_finish(utf8 str) {
if (string_resize(&str, 1))
return false;
string_header_t *hdr = (string_header_t *) (str - sizeof(string_header_t));
*(str + hdr->length) = '\0';
return true;
}
[更新2] Valgrind的日誌(所有這些是與本幾乎相同):
==96370== Invalid read of size 8
==96370== at 0x100011201: string_append_char (string.c:68)
==96370== by 0x100000AE7: test_string (example.c:84)
==96370== by 0x100000BEA: main (example.c:106)
==96370== Address 0x100aac6d0 is 0 bytes inside a block of size 24 free'd
==96370== at 0x1000098B8: realloc (in /usr/local/Cellar/valgrind/HEAD/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==96370== by 0x100011243: string_append_char (string.c:92)
==96370== by 0x100000ADA: test_string (example.c:83)
==96370== by 0x100000BEA: main (example.c:106)
==96370== Block was alloc'd at
==96370== at 0x100009551: calloc (in /usr/local/Cellar/valgrind/HEAD/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==96370== by 0x1000110F2: string_new (string.c:38)
==96370== by 0x100000A5A: test_string (example.c:72)
==96370== by 0x100000BEA: main (example.c:106)
==96370== Invalid write of size 8
==96370== at 0x100011274: string_append_char (string.h:44)
==96370== by 0x100000AE7: test_string (example.c:84)
==96370== by 0x100000BEA: main (example.c:106)
==96370== Address 0x100aac6d8 is 8 bytes inside a block of size 24 free'd
==96370== at 0x1000098B8: realloc (in /usr/local/Cellar/valgrind/HEAD/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==96370== by 0x100011243: string_append_char (string.c:92)
==96370== by 0x100000ADA: test_string (example.c:83)
==96370== by 0x100000BEA: main (example.c:106)
==96370== Block was alloc'd at
==96370== at 0x100009551: calloc (in /usr/local/Cellar/valgrind/HEAD/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==96370== by 0x1000110F2: string_new (string.c:38)
==96370== by 0x100000A5A: test_string (example.c:72)
==96370== by 0x100000BEA: main (example.c:106)
[更新3]一些示例代碼:
void test_string(void) {
utf8 str = string_new();
string_debug(str);
string_append_char(str, 'h');
string_append_char(str, 't');
string_append_char(str, 't');
string_append_char(str, 'p');
string_append_char(str, ':');
string_append_char(str, '/');
string_append_char(str, '/');
string_append_char(str, 'g');
string_append_char(str, 'o');
string_append_char(str, 'o');
string_append_char(str, 'g');
string_append_char(str, 'l');
string_append_char(str, 'e');
string_append_char(str, '.');
string_append_char(str, 'c');
string_append_char(str, 'o');
string_append_char(str, 'm');
string_append_char(str, '/');
string_append_char(str, '?');
string_append_char(str, 's');
string_append_char(str, '=');
string_append_char(str, 'f');
string_append_char(str, 'i');
string_append_char(str, 's');
string_append_char(str, 'h');
//string_finish(str);
printf("String %s", str);
string_dealloc(str);
}
'#define is ==''#define isnt!=' - 請不要! –
你也可以發佈valgrind顯示的錯誤嗎? – Jay
用Valgrind日誌更新了這個問題......我稍微玩了一下,似乎指針沒有被改變......(它仍然指向舊地址)...用於隨後的調用。 –