c - Array resizing and realloc function -
now try improve knowledge of pointers reading "understanding , using c pointers" richard reese.
here's 1 code example book concerning realloc() function.
char* getline(void) { const size_t sizeincrement = 10; char* buffer = malloc(sizeincrement); char* currentposition = buffer; size_t maximumlength = sizeincrement; size_t length = 0; int character; if(currentposition == null) { return null; } while(1) { character = fgetc(stdin); if(character == '\n') { break; } if(++length >= maximumlength) { char *newbuffer = realloc(buffer, maximumlength += sizeincrement); if(newbuffer == null) { free(buffer); return null; } currentposition = newbuffer + (currentposition - buffer); buffer = newbuffer; } *currentposition++ = character; } *currentposition = '\0'; return buffer; } the main idea read symbols buffer until meet \n.
we don't know total number of symbols read it's reasonable use realloc() function expand buffer periodically.
so, expand buffer use:
char *newbuffer = realloc(buffer, maximumlength += sizeincrement); in case realloc() returns newbuffer pointer expanded buffer.
after that, if realloc() invoked successfully, currentposition recalculated as:
currentposition = newbuffer + (currentposition - buffer); question:
is valid recalculate currentposition in such way?
as know, after realloc() invocation buffer pointer invalidated. (see, example, this). access buffer pointer leads undefined behaviour. so... wrong?
this code causes undefined behaviour:
currentposition = newbuffer + (currentposition - buffer); after passing pointer realloc, pointer variable (and other pointers based on pointer) become indeterminate, same status uninitialized variable has.
reference: c11 6.2.4/2:
[...] value of pointer becomes indeterminate when object points (or past) reaches end of lifetime.
then, doing pointer arithmetic on invalid pointer causes undefined behaviour, c11 6.5.6/8:
when expression has integer type added or subtracted pointer, [...] if both pointer operand , result point elements of same array object, or 1 past last element of array object, evaluation shall not produce overflow; otherwise, behavior undefined
the pointer operand doesn't point object @ time. object used point has been freed.
in fact, evaluating pointer @ may cause undefined behaviour, since indeterminate value may trap representation. (imagine system loading value address register performs hardware check address belongs process). refs: c11 3.19.2, 6.2.6.1/5:
if stored value of object has such representation , read lvalue expression not have character type, behavior undefined
the correct way write code have been:
if(++length >= maximumlength) { size_t currentoffset = currentposition - buffer; char *newbuffer = realloc(...... // ... currentposition = newbuffer + currentoffset; buffer = newbuffer; } (personally use offset whole way , instead of currentposition, avoid problem entirely)
Comments
Post a Comment