Is `free (a_comparable_pointer)` correct or UB?

Of course, highlighting and releasing the same pointer is well defined ...

void *p1 = malloc(42);
assert(p1);
...
free(p1);

... and conversion, although it intptr_t/uintptr_tcreates a comparable pointer (as in the case of "compare equal" C11 7.20.1.4) when these integer types exist, although not necessarily the same bit patterns. We can say that p2they p3have the same meaning, but can have different ideas.

void *p2 = malloc(42);
assert(p2);
uintptr_t u2 = (uintptr_t) p2;
...
void *p3 = (void *) u2;

// Specified to evaluate true C11 7.20.1.4
if (p2 == p3) ...

// Maybe true, maybe false
if (memcmp(&p2, &p3, sizeof p2) == 0) ...

// Note - early version of post had this errant code
// if (memset(&p2, &p3, sizeof p2) == 0) ...

Now up free()through the comparable pointer.

The function freecalls up the space that it points ptrto ... if the argument does not match the pointer previously returned by the memory management function ... the behavior is undefined. C11dr §7.22.3.3 3

void *p4 = malloc(42);
assert(p4);
uintptr_t u4 = (uintptr_t) p4;
...
void *p5 = (void *) u4;
...
free(p5);  // UB or not UB?

, , , : "" "" free()?

, free(p5) undefined (UB), . - C, .

+4
5

N1570, ISO C 2011 (C11).

void *p4 = malloc(42);
assert(p4);
uintptr_t u4 = (uintptr_t) p4;
...
void *p5 = (void *) u4;
...
free(p5);  // UB or not UB?

uintptr_t , p4 p5 ; tersely, p4 == p5. == 6.5.9p6 , p4 p5 ( , p3 ).

, . ( , ), , p4 p5 . 6.2.6.1p4:

( NaN) , , , .

( , .)

, free?

6.5.2.2. 4 :

, .

( .)

, free() p5 ( p4), of p5, , p4. , , , , , , free .

+3

uintptr_t , void 1.

, 2.

, : free(p5)


1 ( : ISO/IEC 9899: 201x 7.20.1.4 Integer , 1)
, void , void, : uintptr_t

2 ( : ISO/IEC 9899: 201x 6.5.9 6)
, , ( ) , , - , - , . 109)

+3

, uintptr_t, "compare equal", , void* T* :

void . void ; .

( 6.3.2.3/1 ISO C99)

, UB:

T* p = malloc(n);
...
free(p);

:

void* p0 = malloc(n);
T* p = p0;
...
free(p0);

. , malloc K & R 2nd edition .

+2

free /, , ( void*). , , .

+1

, free , . , . , , , :

int* pn = (int*)malloc(sizeof(int));
pn += 2;                // Now points beyond the beginning of an allocated heap block
void* pv = (void*)pn;   
free(pv);               // Therefore will crash

If you remove pn + = 2, it will become beautiful again. On the bottom line: it’s normal to change and drop the pointers, but when you release them, you need to make sure that they indicate what was actually allocated and has not yet been released.

0
source

Source: https://habr.com/ru/post/1655127/


All Articles