跟踪malloc分配的内存量

min*_*gos 3 c malloc char

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

typedef struct {
    char * str;
    int mem;
} my_string_t;
Run Code Online (Sandbox Code Playgroud)

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

Hea*_*utt 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成员my_string_t:

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

请注意,值p->string不存储在已分配的内存中,它是从分配的内存开头起的四个字节,紧跟在(假定的32位,四字节)整数之后.

您的编译器可能要求您将灵活的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是由str_of_mystr2().它将与第一个示例具有大致相同的值,具体取决于编译器设置打包结构的结尾.

虽然有些人建议跟踪长度,但size_t我会查看一些旧的Dobb博士关于我不同意的文章.支持值大于INT_MAX对您的程序的正确性具有可疑价值.通过使用int,您可以编写assert(p->num_chars >= 0);并进行测试.使用unsigned时,您可以编写等效测试,assert(p->num_chars < UINT_MAX / 2); 只要您编写包含运行时数据检查的代码,使用带符号类型就会很有用.

另一方面,如果你正在编写一个处理超过UINT_MAX/2个字符的字符串的库,我向你致敬.