跟踪 malloc 分配了多少内存

2024-02-14

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

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

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


您将需要在同一内存块中为长度和字符串分配空间。这可能是您对结构的预期目的,但您只为指向字符串的指针保留了空间。

必须分配空间来包含字符串的字符。

例如:



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我会查阅多布博士的一些旧文章来了解我为什么不同意。支持大于 INT_MAX 的值对于程序的正确性来说价值值得怀疑。通过使用 int,你可以写assert(p->num_chars >= 0);并进行测试。对于无符号,您可以编写类似的等效测试assert(p->num_chars < UINT_MAX / 2);只要您编写的代码包含对运行时数据的检查,使用签名类型就会很有用。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

跟踪 malloc 分配了多少内存 的相关文章

随机推荐