代码之家  ›  专栏  ›  技术社区  ›  Claudio Daffra

如何修复C中“realloc后可能会使用旧指针[-Use after free]”的警告?

  •  2
  • Claudio Daffra  · 技术社区  · 7 月前

    在尝试使用realloc重新分配内存时,我的C代码中遇到了一个警告。具体警告是:

    lib/gc.c: In function ‘gcLocalRealloc’:
    lib/gc.c:625:9: warning: pointer ‘old’ may be used after ‘realloc’ [-Wuse-after-free]
      625 |         gcLocalPop ( gc,old ) ;
          |         ^~~~~~~~~~~~~~~~~~~~~
    lib/gc.c:621:11: note: call to ‘realloc’ here
      621 |     ptr = (void*) realloc ( ptr,SIZE ) ;
    

    以下是导致问题的代码:

    void* gcLocalRealloc(gc_t *gc, void* ptr, size_t SIZE) {
        //assert(SIZE!=0); // realloc(array, 0) is not equivalent to free(array).
        if (SIZE == 0) {
            gcFree(ptr);
            return ptr = NULL;
        }
        
        assert(SIZE > 0);
        
        if (ptr == NULL) return gcLocalMalloc(gc, SIZE);
    
        void* old = ptr;
        
        ptr = (void*) realloc(ptr, SIZE);
    
        if (ptr != NULL) {
            gcLocalPop(gc, old);
            gcLocalPush(gc, ptr, SIZE);
            assert(ptr != NULL);
        }
    
        return ptr;
    }
    

    编译器警告说,旧指针在被realloc释放后可能会被使用。如何在保持重新分配内存和更新垃圾回收功能的同时修复此警告?

    提前感谢您的帮助!

    1 回复  |  直到 7 月前
        1
  •  2
  •   Barmar    7 月前

    一旦你打电话 realloc ,如果它返回非空值,则 old (包含前一个指针值)变为 不确定 因此,尝试使用此值(即使您没有取消引用它)可能会导致 undefined behavior .

    在这种情况下,你应该做的就是打电话 gcLocalPop 打电话之前 realloc ,然后打电话 gcLocalPush 无论成功与否。

    void* gcLocalRealloc(gc_t *gc, void* ptr, size_t SIZE) {
        if (SIZE == 0) {
            gcFree(ptr);
            return ptr = NULL;
        }
        
        assert(SIZE > 0);
        if (ptr == NULL) return gcLocalMalloc(gc, SIZE);
    
        int old_size = gcLocalPop(gc, ptr);
        void* old = ptr;
        
        ptr = realloc(ptr, SIZE);
    
        if (ptr != NULL) {
            gcLocalPush(gc, ptr, SIZE);
            return ptr;
        } else {
            gcLocalPush(gc, old, old_size);
            return old;
        }
    }
    

    请注意,您必须进行修改 gcLocalPop 在需要放回物品的情况下,返回被移除物品的尺寸 realloc 失败。