跟踪malloc分配的内存量

时间:2010-01-08 22:47:06

标签: c malloc char

在对SO的相关问题进行快速扫描之后,我推断出没有能够检查malloc已分配给指针的内存量的函数。我正在尝试使用C中的简单char *来复制一些std :: string基本功能(主要是动态大小),并且不想一直调用realloc。我想我需要跟踪已经分配了多少内存。为了做到这一点,我正在考虑创建一个包含字符串本身的typedef和一个当前分配的内存量的整数,如下所示:

typedef struct {
    char * str;
    int mem;
} my_string_t;

这是一个最佳解决方案,或者您可以提出一些能够带来更好结果的建议吗?在此先感谢您的帮助。

6 个答案:

答案 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