GCC 初始化结构时出现“AddressSanitizer: heap-buffer-overflow”

GCC "AddressSanitizer: heap-buffer-overflow" when initializing struct

提问人:CyanDev 提问时间:7/8/2021 最后编辑:CyanDev 更新时间:7/8/2021 访问量:399

问:

我一直在写一个 VM/Interpreter 组合的东西,我不知道如何准确描述它。

一切都按预期进行,现在在我有数百行代码之前,我想进入 Garba Collection,因为有些指针以某种方式以某种方式丢失了。并不是说我没有删除指针,而是我创建了指针,但它们不知何故迷失在解释/运行代码的过程中。

所以,我想追踪他们。我以某种方式编写了自己的“内存管理器”,它只是一个 ,我收集了所有指针。std::vector

为了跟踪和分配指针,我有以下代码:

struct MemBlock {
    bool free;
    void* ptr;
    size_t size;
};

std::vector<MemBlock*> mem;
size_t max_size;
size_t mem_size;
int count = 0;

void mem_init(size_t maxSize) {
    max_size = size/sizeof(MemBlock*);
}

void* mem_alloc(size_t size) {
    for (int i = 0; i < count; i++) {
        MemBlock* block = mem[i];

        if (block->free) {
            mem_size -= block->size;
            mem_size += size;
            block->free = false;
            block->ptr = malloc(size);
            block->size = size;

            if (block->ptr == nullptr) {
                throw std::exception();
            }
            return block->ptr;
        }
    }

    void* ptr = malloc(sizeof(size));

    if (ptr == nullptr) {
        throw PointerNullException();
    }

    MemBlock* block = (MemBlock*) malloc(sizeof(MemBlock));
    *block = (MemBlock) {
        false,
        ptr,
        size
    };

    mem_size += size;
    count++;

    mem.push_back(block);
    return block->ptr;
}

但是,当我使用并初始化指针内的对象时:mem_alloc()

Int* i = (Int*) mem_alloc(sizeof(Int));
*i = (Int) {};    // -- Here
i->value = atoi(advance().c_str());

GCC AdressSanitizer 显示以下错误:

==5939==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000098 at pc 0x555963d82fc5 bp 0x7fff4ec39070 sp 0x7fff4ec39060
WRITE of size 4 at 0x602000000098 thread T0

如果我删除所述线,那么它只会发生在 nex 线上。指针确实指向有效的内存位置,如果不是,它应该引发异常。 当然,我确信我错过了什么/做错了什么。

但我不知道是什么。我就是这样学会的,或者至少是我所理解的......

编辑:这将是一个最小的可重现示例:

#include <iostream>
#include <stdlib.h>
#include <vector>

struct Object {
    const char* type;
};

template <typename T>
struct Primitive : Object {
    T value;
};

struct Int : Primitive<int> {
    const char* type = "int";
};

struct MemBlock {
    bool free;
    void* ptr;
    size_t size;
};

std::vector<MemBlock*> mem;
size_t mem_size = 0;
int count = 0;

void* mem_alloc(size_t size) {
    for (int i = 0; i < count; i++) {
        MemBlock* block = mem[i];

        if (block->free) {
            mem_size -= block->size;
            mem_size += size;
            block->free = false;
            block->ptr = malloc(size);
            block->size = size;

            if (block->ptr == nullptr) {
                throw std::exception();
            }
            return block->ptr;
        }
    }

    void* ptr = malloc(sizeof(size));

    MemBlock* block = (MemBlock*) malloc(sizeof(MemBlock));
    *block = (MemBlock) {
        false,
        ptr,
        size
    };

    mem_size += size;
    count++;

    mem.push_back(block);

    std::cout << "HI" << std::endl;    
    return block->ptr;
}
void mem_free(void* ptr) {
    for (int i = 0; i < count; i++) {
        MemBlock* block = mem[i];

        if (block->ptr == ptr) {
            free(ptr);

            mem_size -= block->size;
            block->size = 0;
            block->ptr = nullptr;
            block->free = true;
        }
    }
}

int main() {
    // Create new Integer-Object
    Int* i = (Int*) mem_alloc(sizeof(Int));


    std::cout << "[Pointer]: " << i << std::endl;

    *i = (Int) {};
    i->value = 5;

    std::cout << "[Value]: " << i->value << std::endl;
}
C++ GCC malloc

评论

1赞 user4581301 7/8/2021
我不得不对此进行大量修改才能获得一个兼容的例子。这提供了大量机会,可以意外地添加错误并给你一个错误的答案)或意外地修复错误(并且没有给你答案)。考虑构建一个最小的可重现示例。很有可能,仅仅制作 MRE 就会减少足够多的噪音,以便您找到并修复错误,但如果没有,请将 MRE 添加到问题中。
1赞 Retired Ninja 7/8/2021
void* ptr = malloc(sizeof(size));你确定你想要那里吗?如果您将一个最小的可重现示例放在一起来演示该问题,将会有所帮助。sizeof
3赞 NathanOliver 7/8/2021
*block = ...是未定义的行为。 不创建对象,它只分配内存,因此没有指向 by 供您分配。mallocMemBlockblock
0赞 CyanDev 7/8/2021
我添加了一个最小的可重复示例。我敢肯定,我想使用 ,因为它在分配的内存中创建对象。从我读过很多遍的内容来看。*block = ...
0赞 Richard Critten 7/8/2021
替换为返回的块中的新位置,情况可能会有所改善(无法承受对齐问题)。Int* i = (Int*) mem_alloc(sizeof(Int)); *i = (Int) {}; // -- Heremem_alloc

答:

0赞 CyanDev 7/8/2021 #1

好吧,多亏了 Retired NinjaRichar Critten,我得到了解决方案。

我曾经将内存分配给指针,这当然是错误的。我想经过几个小时的编码后,我的头几乎不对劲了。mem_alloc()sizeof(size)

但我想这个问题现在已经解决了。