新指针(通过malloc)与释放/旧指针之一相同

新指针(通过malloc)与释放/旧指针之一相同,c,pointers,heap-memory,C,Pointers,Heap Memory,我试图在C中出现自由错误后跟踪使用情况。 我的问题是,如果我有这样的代码: A * ptrA = malloc(sizeof(A)); A * aliasA = ptrA; // do something ' free(ptrA) // some other code B * ptrB = malloc(sizeof(B)); // assume this return same pointer as ptrA //trying to use aliasA here 只是想知道aliasA

我试图在C中出现自由错误后跟踪使用情况。 我的问题是,如果我有这样的代码:

A * ptrA = malloc(sizeof(A));
A * aliasA = ptrA;
// do something ' 
free(ptrA) 
// some other code
B * ptrB = malloc(sizeof(B)); // assume this return same pointer as ptrA
//trying to use aliasA here
只是想知道aliasA的使用是否是UAF错误? 如果是,这里出了什么问题

为了澄清这个问题,我认为最好添加一个小例子:

int main(){
    int *ptr = (int *)malloc(4);
    *ptr = 5;
    int *ptr2 = ptr;
    printf("%d\n", *ptr);
    free(ptr);

    int *new_ptr = malloc(4);
    *new_ptr = 66;
    printf("%d\n", *ptr2);

    return 0;
}  
输出为:

5
66
(我在S2E中选中了
ptr
new\u ptr
:这两个指针实际上指向相同的地址。释放ptr后,相同的地址分配给new\u ptr。)

从上面的输出来看,
ptr2
的使用似乎给出了与
new\u ptr
相同的输出

当我编写检测UAF错误的解决方案时,我记录了指针的信息。指针的值存储为
uint64\t
,布尔类型
标志
用于声明指针是否处于活动状态

因此,我猜想当
new_ptr
ptr
指向同一地址时会出现问题,因为一旦调用
malloc()
,新_ptr的
标志将变为
true
。之后,当我使用
ptr
时,我无法检测到此UAF错误,因为此地址被标记为活动


提前谢谢

aliasA
是UAF错误,它可能与
ptrA
保持相同的值,但不能保证,建议将释放的指针(aliasA和ptrA)重新分配到
NULL
,以避免错误

在您的情况下,最好在
free
之后分配
NULL

free(ptrA);
free(aliasA);
ptrA = NULL;
aliasA = NULL;
这是一个UAF错误

实际上,第二个
malloc()
调用不太可能返回与
aliasA
相同的地址,因为无法保证该行为。你不应该依赖它

你可能会问:我能比较一下他们的地址吗?不,比较可能对您有意义,但它是未定义的行为,因为指针相等性比较只有在两个指针指向同一数组中的不同元素时才有效。在这种情况下,两个分配的块肯定不是同一个数组,因此这些指针之间的比较没有很好的定义

最后,您不应该依赖由
malloc()
返回的地址。您所能做的就是在调用时请求的内存量内使用它

在实践中,这是一种很好的方法。如果不取消对指针的引用,则取决于“免费后使用”的定义是否构成“免费后使用”。例如,并不是只讨论使用指针值,而是讨论取消引用它,即使用已释放的对象

然而,C标准规定,即使使用指针值,也有未定义的行为:

  • 在以下情况下,该行为未定义:

    [……]

    • 使用指向通过调用free或realloc函数释放的空间的指针值(7.22.3)
  • 这是因为:

    当指针指向(或刚刚经过)的对象到达其生命周期结束时,指针的值将变得不确定

    因此,以下代码具有未定义的行为:

    A *ptrA = malloc(sizeof(A));
    A *aliasA = ptrA;
    free(ptrA);
    A *ptrB = malloc(sizeof(A));
    
    if (aliasA == ptrB) { // undefined behaviour, as it might be a trap
        printf("We were given the same pointer");
    }
    

    这里的比较没有意义,编译器可以自由地进行任何优化,因为
    aliasA
    不再需要包含有效值。编译器甚至可以在
    aliasA
    中设置陷阱,这将导致程序在带有诊断消息的
    if
    语句处中止。或者,即使它们被赋予了不同的内存地址,它们也可能指向相同的地址,反之亦然。

    您有理由怀疑
    malloc
    将返回相同的地址两次吗?除了请求指向特定大小的块的指针之外,您不能对malloc的行为进行任何假设,假设没有错误,你会得到一个指向至少与你要求大小相同的块的指针。什么是UAF错误?@coderredoc Free后使用。这对我来说是新的。是的,这是一个UAF错误。不,不管
    malloc
    是否再次返回相同的地址(这是允许的),您仍然使用不应该使用的指针。取消引用和赋值是两件不同的事情:)注释不是添加信息的好地方。你应该把它写进你的答案中:)我不明白为什么即使在更正之后,它仍然是反对票??不会帮助别人吗??这是严重的负面影响吗?NMDV,但
    A*aliasA=ptrA出现在
    空闲(ptrA)
    之前,因此“别名a
    为UAF错误”不清楚。更糟糕的是
    A*aliasA=ptrA;免费(ptrA);免费(a)
    是一个UAF错误。感谢您的建议,基本上,我是故意编写此代码的,因为我希望发出错误消息。这不是严格正确的。指针相等是在任何地方定义的-否则与NULL的比较将不正确。这仅仅是因为前一个指针引用的对象的生命周期已经结束,其值是不确定的。