【发布时间】:2017-06-13 14:37:18
【问题描述】:
我想实现类似this 的东西,其中本机内存分配在Java 堆上。为了让它工作,我需要这个代码子集来工作:
const static int pad = 16;
void * operator new(size_t t) throw(std::bad_alloc) {
void* padded = malloc((int) t + pad);
void* p = static_cast<void *>(static_cast<char *>(padded) + pad);
std::cout << "new: " << p << " padded " << padded << " size: " << t << std::endl;
return p;
}
void operator delete(void *p) throw() {
if (p != 0) {
void *padded = static_cast<void *>(static_cast<char *>(p) - pad);
std::cout << "del: " << p << " padded " << padded << std::endl;
free(padded);
} else {
std::cout << "pointer is zero!" << std::endl;
}
}
我要做的是在每个内存分配中添加一些字节。这似乎工作正常(大多数删除都是成功的),但我收到一个错误:
java(379,0x700002206000) malloc: *** error for object 0x7fc104122180: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
堆栈跟踪表明free 是从该行立即调用的(即,不是我的delete):
name = temp.str();
其中name 是string,temp 是stringstream。我尝试在非 JNI 上下文中重现此错误,但它并没有在那里崩溃。
如果我像这样填充内存,那么显然将通过new 分配的free 或直接从malloc 分配的delete 分配是错误的。这可能吗?
在我的标准输出中搜索错误地址支持这一点:
new: 0x7fc104122190 padded 0x7fc104122180 size: 32
del: 0x7fc104122190 padded 0x7fc104122180
new: 0x7fc104122180 padded 0x7fc104122170 size: 32
看起来地址已成功分配然后解除分配。与打印到标准输出的最后一行中未填充的地址相同的地址再次出现(我认为该地址最终成为第二次分配中的未填充地址是巧合)。但由于这是打印到标准输出的最后一行,因此对 free 的尝试失败并没有通过我看到的代码(即使我覆盖了 free 本身)。
是否有可能让这种方法发挥作用?还是我必须将我的new/delete 的范围缩小到我自己完全管理的对象?
【问题讨论】:
-
请注意:在
operator new或operator delete内部使用C++ 流可能会遇到麻烦;有时流操作使用new和delete,如果发生这种情况,一切都会崩溃。 C I/O 没问题,因为它对new和delete一无所知。 -
@RawN:这无关紧要——重载
operator new的整个想法是从一些非标准的内存源分配内存。 “Java 堆”听起来像是一个合理的来源。 -
@PeteBecker,即使我评论我的 cout 行,我也会遇到问题。
标签: c++ malloc new-operator free delete-operator