黑客C ++动态数组的大小 [英] Hacking C++ dynamic array size

查看:169
本文介绍了黑客C ++动态数组的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

纯粹的好奇心,而不是在生产中使用,因为很明显,这可能导致重大问题。

Pure curiosity, not to be used in production, because obviously it could cause major problems.

使用C ++,当你分配新的内存( VAR * CH =新的char [X] ),大小本质上是存储在 CH [ -1] 按照C ++规范。

With C++, when you allocate new memory (var *ch = new char[x]), the size is stored essentially in ch[-1] according to the C++ specs.

现在的问题是,是否有一种方式来获得价值?我试过:

The question is, is there a way to get that value? I've tried:

char* ptr = ch;
--ptr
cout << *ptr;

// AND

cout << ch[-sizeof(char)];

那么,有没有办法破解吗?同样,纯粹的好奇。

So is there a way to hack this? Again, pure curiosity.

推荐答案

免责声明:永远不要指望这个工作。考虑这个唯一的玩具code和从来没有真正的软件使用它!

很多时候,在运营商最终调用正确的的malloc(),这是众所周知的表现出这种行为libc中的许多版本。

Often times, the new operator ends up calling right to malloc(), which is known to exhibit this behavior in many versions of libc.

与code的问题是,你的指针是一个的char * ,但你后的数据可能是一个真正的为size_t (32位系统上的4个字节)。

The problem with your code is that your pointer is a char* but the data you're after is probably really a size_t (4 bytes on a 32-bit system).

以下code确实演​​示的几乎的你追求的:

The following code does demonstrate almost what you're after:

#include <stddef.h>        // for size_t
#include <stdio.h>

void test(size_t size) {
    size_t result;
    char* p = new char[size];

    result = *((size_t*)p - 1);
    printf("Allocated:  %d (0x%X)  Preceding value: %d (0x%X)\n",
        size, size, result, result);

    delete p;
}

int main() {
    test(1);
    test(40);
    test(100);
    test(0x100);
    test(6666);
    test(0xDEAD);
    return 0;
}

请注意,我第一次铸造 P 为size_t * ,再减去1(这相当于的sizeof(为size_t)字节)。

Note that I'm first casting p to a size_t*, and then subtracting 1 (which equates to sizeof(size_t) bytes).

输出:

$ ./a.exe
Allocated:  1 (0x1)  Preceding value: 19 (0x13)
Allocated:  40 (0x28)  Preceding value: 51 (0x33)
Allocated:  100 (0x64)  Preceding value: 107 (0x6B)
Allocated:  256 (0x100)  Preceding value: 267 (0x10B)
Allocated:  6666 (0x1A0A)  Preceding value: 6675 (0x1A13)
Allocated:  57005 (0xDEAD)  Preceding value: 57019 (0xDEBB)

所以输出的关闭

从glibc的望着的malloc / malloc.c ,我们看到了以下评论:

Looking at malloc/malloc.c from glibc, we see the following comment:

  Alignment:                              2 * sizeof(size_t) (default)
       (i.e., 8 byte alignment with 4byte size_t). This suffices for
       nearly all current machines and C compilers. However, you can
       define MALLOC_ALIGNMENT to be wider than this if necessary.

  Minimum overhead per allocated chunk:   4 or 8 bytes
       Each malloced chunk has a hidden word of overhead holding size
       and status information

  Minimum allocated size: 4-byte ptrs:  16 bytes    (including 4 overhead)
              8-byte ptrs:  24/32 bytes (including, 4/8 overhead)

这是极好的线索。有两件事情很可能发生的事情:

These are excellent clues. There are two things that are probably happening:


  1. 您请求的分配大小对齐到下一个调整大小。

  2. 的最低位(不是因为上述对准的使用)用于此状态信息。

所以我们增加code,显示数字,一起玩的规则:

So we add the code to show numbers that "play along" with these rules:

#define SIZE        sizeof(size_t)
#define MAX(x,y)    ((x)>(y) ? (x) : (y))
#define align(x)    (((x)+2*SIZE-1) & ~(2*SIZE-1))
#define mask(x)     ((x) & ~0x3)

printf("align(size): 0x%X   mask(result): 0x%X\n\n",
    align(MAX(size+SIZE, 16)), mask(result));

大小还包括尺寸,并且必须至少为16。然后,这个值被调整到下一个2 *尺寸多。我们读出的结果具有底部的2位与运算了。这些都是状态信息,结果是:

The size also includes SIZE, and must be at least 16. This value is then aligned to the next 2*SIZE multiple. And the result we read out has the bottom 2 bits ANDed off. These are the "status information. The result:

$ ./a.exe
sizeof(size_t) = 4

size:  1 (0x1)  result: 19 (0x13)
align(size): 0x10   mask(result): 0x10

size:  40 (0x28)  result: 51 (0x33)
align(size): 0x30   mask(result): 0x30

size:  100 (0x64)  result: 107 (0x6B)
align(size): 0x68   mask(result): 0x68

size:  256 (0x100)  result: 267 (0x10B)
align(size): 0x108   mask(result): 0x108

size:  6666 (0x1A0A)  result: 6675 (0x1A13)
align(size): 0x1A10   mask(result): 0x1A10

size:  57005 (0xDEAD)  result: 57019 (0xDEBB)
align(size): 0xDEB8   mask(result): 0xDEB8

和你有它!

请注意,我使用:

$ uname
CYGWIN_NT-6.1-WOW64

$ g++ --version
g++ (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)

同样,这是高度实现特定的,不应该被信任。但是,这是事实,许多分配器的内存实际块之前存储分配大小合适的。

Again, this is highly implementation-specific and should never be trusted. However, it is true that many allocators store the allocation size right before the actual block of memory.

另请参阅:

  • Where Do malloc() / free() Store Allocated Sizes and Addresses?
  • glibc malloc/malloc.c - especially "malloc_chunk details" around line 1119

这篇关于黑客C ++动态数组的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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