是否的malloc()分配内存的连续的块? [英] Does malloc() allocate a contiguous block of memory?

查看:148
本文介绍了是否的malloc()分配内存的连续的块?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  typedef结构ts_request
{
  ts_request_buffer_header_def头;
  炭包[1];
} ts_request_def;ts_request_buffer_def * request_buffer =
的malloc(的sizeof(ts_request_def)+(2 * 1024 * 1024));

程序员基本上是工作的一个缓冲区溢出的概念。我知道code看起来狡猾。所以我的问题是:


  1. 难道永远的malloc分配的内存连续块?因为在这个code。如果块是不连续的,在code将失败大时间


  2. 做免费(request_buffer),将其分配给无所有字节的malloc即的sizeof(ts_request_def)+(2 * 1024 * 1024),
    或仅在结构的sizeof的大小的字节(ts_request_def)


  3. 你看到这种方法的任何明显的问题,我需要跟我的老板讨论这个问题,并希望本办法指出任何漏洞



解决方案

要回答您的编号点。



  1. 所有字节。的malloc /自由不知道或不关心对象的类型,只是大小。

  2. 这是严格地说不确定的行为,但一个共同的把戏许多实现的支持。请参见下面的其他办法。

最新的C标准,ISO / IEC 9899:1999(非正式C99),允许灵活的阵列成员

这方面的一个例子是:

  INT主要(无效)
{
    结构{为size_t X;所以char a []; } * P;
    P =的malloc(sizeof的* P + 100);
    如果(p)的
    {
        / *您现在可以访问到对 - >一种[99]安全* /
    }
}

允许您避免使用常见的,现在这个标准的功能,但不规范,你在你的问题描述的实现扩展。严格来说,使用非灵活数组成员访问,并超出其范围是不确定的行为,但许多实现文件,并鼓励它。

此外, GCC 允许的零长度数组的作为扩展。零长度数组是非法的标准C,但海湾合作委员会推出这项功能之前C99给我们灵活的数组成员。

在一个评论的回应,我会解释为什么下面的代码片段在技术上是未定义的行为。节号我引用参考C99(ISO / IEC 9899:1999)

 结构{
    CHAR ARR [1];
} *X;
X =的malloc(sizeof的* X + 1024);
X-GT&;常用3 [23] = 42;

首先,6.5.2.1#2示出了由[i]是相同的(*((A)+(i))的),因此,X->改编[23]等价于(*((X->改编)+(23)))。现在,6.5.6#8(上增加了一个指针和一个整数)说:


  

如果指针操作数和结果指向相同的数组对象,或者一个过去的数组对象的最后一个元素的元素两者的评估也不得产生溢出,否则,的行为是不确定的


由于这个原因,因为X->改编[23]是不是在阵列内,该行为是不确定的。你可能仍然觉得这没关系,因为的malloc()意味着数组现已延长,但这不是严格的情况下。资料性附录J.2(其中列出了未定义的行为的例子)提供了进一步的澄清一个例子:


  

这是数组下标超出范围,即使对象是显然访问
  定标(如在左值前pression一个[1] [7]指定的声明INT
  一个[4] [5])(6.5.6)。


I have a piece of code written by a very old school programmer :-) . it goes something like this

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

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

the programmer basically is working on a buffer overflow concept. I know the code looks dodgy. so my questions are:

  1. Does malloc always allocate contiguous block of memory ?. because in this code if the blocks are not contiguous , the code will fail big time

  2. Doing free(request_buffer) , will it free all the bytes allocated by malloc i.e sizeof(ts_request_def) + (2 * 1024 * 1024), or only the bytes of the size of the structure sizeof(ts_request_def)

  3. Do you see any evident problems with this approach , i need to discuss this with my boss and would like to point out any loopholes with this approach

解决方案

To answer your numbered points.

  1. Yes.
  2. All the bytes. Malloc/free doesn't know or care about the type of the object, just the size.
  3. It is strictly speaking undefined behaviour, but a common trick supported by many implementations. See below for other alternatives.

The latest C standard, ISO/IEC 9899:1999 (informally C99), allows flexible array members.

An example of this would be:

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 */
    }
}

This now standardized feature allowed you to avoid using the common, but non-standard, implementation extension that you describe in your question. Strictly speaking, using a non-flexible array member and accessing beyond its bounds is undefined behaviour, but many implementations document and encourage it.

Furthermore, gcc allows zero-length arrays as an extension. Zero-length arrays are illegal in standard C, but gcc introduced this feature before C99 gave us flexible array members.

In a response to a comment, I will explain why the snippet below is technically undefined behaviour. Section numbers I quote refer to C99 (ISO/IEC 9899:1999)

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

Firstly, 6.5.2.1#2 shows a[i] is identical to (*((a)+(i))), so x->arr[23] is equivalent to (*((x->arr)+(23))). Now, 6.5.6#8 (on the addition of a pointer and an integer) says:

"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."

For this reason, because x->arr[23] is not within the array, the behaviour is undefined. You might still think that it's okay because the malloc() implies the array has now been extended, but this is not strictly the case. Informative Annex J.2 (which lists examples of undefined behaviour) provides further clarification with an example:

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).

这篇关于是否的malloc()分配内存的连续的块?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆