在对SO的相关问题进行快速扫描之后,我推断出没有能够检查malloc已分配给指针的内存量的函数。我正在尝试使用C中的简单char *来复制一些std :: string基本功能(主要是动态大小),并且不想一直调用realloc。我想我需要跟踪已经分配了多少内存。为了做到这一点,我正在考虑创建一个包含字符串本身的typedef和一个当前分配的内存量的整数,如下所示:
typedef struct {
char * str;
int mem;
} my_string_t;
这是一个最佳解决方案,或者您可以提出一些能够带来更好结果的建议吗?在此先感谢您的帮助。
答案 0 :(得分:5)
您需要在同一内存块中为长度和字符串分配空间。这可能是您对结构的意图,但是您只为指向字符串的指针保留了空间。
必须分配空格以包含字符串的字符。
例如:
typedef struct { int num_chars; char string[]; } my_string_t; my_string_t * alloc_my_string(char *src) { my_string_t * p = NULL; int N_chars = strlen(src) + 1; p = malloc( N_chars + sizeof(my_string_t)); if (p) { p->num_chars = N_chars; strcpy(p->string, src); } return p; }
在我的示例中,要访问指向字符串的指针,请说明string
的{{1}}成员:
my_string_t * p = alloc_my_string("hello free store."); printf("String of %d bytes is '%s'\n", p->num_chars, p->string);
请注意,由于分配了用于存储字符的空间,因此您正在获取字符串的指针。您分配的资源是字符的存储空间,获得的指针是对分配的存储的引用。
在我的示例中,分配的内存按顺序排列如下:
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ | 00 | 00 | 00 | 11 | 'h'| 'e'| 'l'| 'l'| 'o'| 20 | 'f'| 'r'| 'e'| 'e'| 20 | 's'| 't'| 'o'| 'r'| 'e'| '.'| 00 | +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ ^^ ^ || | p| | p->num_chars p->string
请注意,my_string_t
的值不存储在已分配的内存中,它是从分配的内存开头起的四个字节,紧跟在(假定的32位,四字节)整数之后。 / p>
您的编译器可能要求您将灵活的C数组声明为:
typedef struct { int num_chars; char string[0]; } my_string_t;
但缺少零的版本据称符合C99标准。
你可以完成没有数组成员的等价物,如下所示:
typedef struct { int num_chars; } mystr2; char * str_of_mystr2(mystr2 * ms) { return (char *)(ms + 1); } mystr2 * alloc_mystr2(char *src) { mystr2* p = NULL; size_t N_chars = strlen(src) + 1; if (N_chars num_chars = (int)N_chars; strcpy(str_of_mystr2(p), src); } return p; } printf("String of %d bytes is '%s'\n", p->num_chars, str_of_mystr2 (p));
在第二个示例中,等效于p->string
的值由p->string
计算。它将与第一个示例具有大致相同的值,具体取决于编译器设置打包结构的结尾。
虽然有些人会建议跟踪str_of_mystr2()
中的长度,但我会查看一些旧的Dobb博士关于我不同意的文章。支持值大于INT_MAX对您的程序的正确性具有可疑价值。通过使用int,您可以编写size_t
并进行测试。使用unsigned时,您可以编写类似assert(p->num_chars >= 0);
的等效测试。只要编写包含运行时数据检查的代码,使用带符号类型就会很有用。
另一方面,如果你正在编写一个处理超过UINT_MAX / 2个字符的字符串的库,我向你致敬。
答案 1 :(得分:2)
这是显而易见的解决方案。当你在它的时候,你可能想要一个结构成员来维护实际使用的已分配内存量。这将避免必须一直调用strlen(),并使您能够支持非空终止字符串,就像C ++ std :: string类那样。
答案 2 :(得分:1)
这就是它在更新世中的表现,这就是你今天应该怎么做的。你已经死钱了,malloc没有提供任何可移植的,支持的机制来查询分配块的大小。
答案 3 :(得分:1)
更常见的方法是包装malloc(和realloc)并保留大小和指针列表 这样你就不需要改变任何字符串函数了。
答案 4 :(得分:1)
编写包装函数。如果您正在使用malloc,那么无论如何都应该这样做。
有关“编写可靠代码”的示例,请参阅
答案 5 :(得分:1)
我认为你可以使用malloc_usable_size。