c - malloc() 是否分配连续的内存块?

标签 c coding-style malloc

我有一段代码是一个非常老派的程序员写的:-)。它是这样的

typedef struct ts_request
{ 
  ts_request_buffer_header_def header; 
  char                         package[1]; 
} ts_request_def; 

ts_request_def* request_buffer = 
malloc(sizeof(ts_request_def) + (2 * 1024 * 1024));

程序员基本上是在研究缓冲区溢出的概念。我知道代码看起来很狡猾。所以我的问题是:

  1. malloc 是否总是分配连续的内存块?因为在这段代码中,如果 block 不连续,代码将失败很多次

  2. 执行 free(request_buffer) ,它会释放 malloc 分配的所有字节,即 sizeof(ts_request_def) + (2 * 1024 * 1024), 或者只有结构大小的字节 sizeof(ts_request_def)

  3. 您是否发现这种方法有任何明显的问题,我需要与我的老板讨论这个问题,并想指出这种方法的任何漏洞

最佳答案

回答你的编号点。

  1. 是的。
  2. 所有字节。 Malloc/free 不知道也不关心对象的类型,只关心大小。
  3. 严格来说这是未定义的行为,但是许多实现都支持的常见技巧。请参阅下文了解其他替代方案。

最新的 C 标准 ISO/IEC 9899:1999(非正式的 C99)允许 flexible array members .

这方面的一个例子是:

int main(void)
{       
    struct { size_t x; char a[]; } *p;
    p = malloc(sizeof *p + 100);
    if (p)
    {
        /* You can now access up to p->a[99] safely */
    }
}

这个现在标准化的功能允许您避免使用您在问题中描述的常见但非标准的实现扩展。严格来说,使用非灵活数组成员并越界访问是未定义的行为,但许多实现记录并鼓励这样做。

此外,gcc允许 zero-length arrays作为扩展。零长度数组在标准 C 中是非法的,但 gcc 在 C99 为我们提供灵活的数组成员之前引入了此功能。

在对评论的回复中,我将解释为什么下面的代码片段在技术上是未定义的行为。我引用的节号是指 C99 (ISO/IEC 9899:1999)

struct {
    char arr[1];
} *x;
x = malloc(sizeof *x + 1024);
x->arr[23] = 42;

首先,6.5.2.1#2 显示 a[i] 等同于 (*((a)+(i))),所以 x->arr[23] 等价于 (*((x->arr )+(23)))。现在,6.5.6#8(关于添加指针和整数)说:

"If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined."

因此,因为 x->arr[23] 不在数组内,所以行为未定义。您可能仍然认为这没关系,因为 malloc() 暗示数组现在已被扩展,但严格来说并非如此。信息性附件 J.2(列出了未定义行为的示例)通过示例提供了进一步的说明:

An array subscript is out of range, even if an object is apparently accessible with the given subscript (as in the lvalue expression a[1][7] given the declaration int a[4][5]) (6.5.6).

关于c - malloc() 是否分配连续的内存块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/625270/

相关文章:

c - 使用指针构建链表

c# - 对于 C#,是否有替代 xml 文档注释的好方法?

java - 实例化用户定义类型集合的约定是什么?

c - 如何计算字符串中的字符数(如果没有占用所有空间)

c - 如何初始化一个 n 维的多维数组,其中 n 是 C 中用户的输入?

无法从 C 中的结构访问 ** 变量作为数组

ruby - 一行 `if` return 语句有两个 Action

c - 如何在C中为二维数组中的每个元素动态分配内存

c++ - 为什么我们不能从 void* 隐式分配给 C++ 中的任何其他类型,但它在 C 中更受欢迎?

c++ - 使用指针的 strcat 实现