黑客C ++动态数组的大小 [英] Hacking C++ dynamic array size
问题描述
纯粹的好奇心,而不是在生产中使用,因为很明显,这可能导致重大问题。
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:
- 您请求的分配大小对齐到下一个调整大小。
- 的最低位(不是因为上述对准的使用)用于此状态信息。
所以我们增加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这样做的malloc()/ free()的存储分配尺寸和地址?
- 的glibc
的malloc / malloc.c
- 尤其是个malloc_chunk细节
绕行1119
- Where Do malloc() / free() Store Allocated Sizes and Addresses?
- glibc
malloc/malloc.c
- especially "malloc_chunk details
" around line 1119
这篇关于黑客C ++动态数组的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!