Проблема с Realloc () в C. всегда висит, но компилируется нормально
-
01-10-2019 - |
Вопрос
У меня проблемы с программой, которая предназначена для того, чтобы быть строковым буфером, в частности, эта функция предназначена для сброса буфера со строкой CSTR. Если CSTR имеет значение NULL, то содержание должно быть сброшено к пустую CHAR ' 0'. Он всегда висит на втором наборе Realloc, где он изменяет размер Buf-> Содержание, которое я понятия не имею, почему это. Любая помощь была бы потрясающей.
Структура:
typedef struct strbuf {
char *contents;
size_t length;
} StringBuffer;
Это называется из
strbuf_reset(sb, NULL)
Вот функция strbuf_reset, которая имеет проблему.
StringBuffer *strbuf_reset(StringBuffer *buf, const char *cstr)
{
if(buf == NULL)
return NULL;
StringBuffer *tempBuf = NULL ;
if(cstr == NULL)
tempBuf = (StringBuffer*)realloc(buf,sizeof(StringBuffer) + sizeof(char));
else
tempBuf = (StringBuffer*)realloc(buf,sizeof(buf) + strlen(cstr)*sizeof(char));
if(tempBuf == NULL)
return NULL;
if(cstr == NULL)
tempBuf->contents = (char*)realloc(buf->contents,sizeof(char));
else
tempBuf->contents = (char*)realloc(buf->contents,(sizeof(buf->contents) + strlen(cstr)*sizeof(char) + 1));
if(tempBuf->contents == NULL){
free(tempBuf);
return NULL;
}
buf = tempBuf;
if(cstr == NULL)
buf->contents = '\0';
else
strcat(buf->contents,cstr);
buf->length = strlen(buf->contents);
return buf;
}
С чем я считаю предложенными изменениями ...
StringBuffer *strbuf_reset(StringBuffer *buf, const char *cstr)
{
if(buf == NULL)
return NULL;
StringBuffer *tempBuf = NULL ;
if(cstr == NULL)
tempBuf = (StringBuffer*)realloc(buf,sizeof(StringBuffer) + sizeof(char) + 10);
else
tempBuf = (StringBuffer*)realloc(buf,sizeof(buf) + strlen(cstr)*sizeof(char)+ 1);
if(tempBuf != NULL)
buf = tempBuf;
else
return NULL;
if(cstr == NULL)
tempBuf->contents = (StringBuffer*)realloc(buf->contents,sizeof(StringBuffer) + sizeof(char) + 10);
else
tempBuf->contents = (StringBuffer*)realloc(buf->contents,sizeof(buf) + strlen(cstr)*sizeof(char)+ 1);
if(tempBuf != NULL)
buf->contents = tempBuf->contents;
else
return NULL;
if(cstr == NULL)
buf->contents = '\0';
else
strcat(buf->contents,cstr);
buf->length = strlen(buf->contents);
return buf;
}
Решение
Поскольку вы собираетесь перезаписать содержимое StringBuffer, используя RealLoc не имеет смысла. Он не сэкономит вам какие-либо распределение памяти, а вместо этого будет скопировать старые данные, которые вы намерены перезаписать все равно. Используйте нормальный malloc и бесплатно.
С вашей оригинальной структурой
typedef struct strbuf {
char *contents;
size_t length;
} StringBuffer;
strbuf_reset устанавливает Buf в CSTR. По успеху возвращает Buf, на неудачу нулевой.
StringBuffer *strbuf_reset(StringBuffer *buf, const char *cstr)
{
if (!buf) return NULL;
if (!cstr) cstr = "";
size_t len = strlen(cstr);
if (len > buf->length) {
char *new_contents = malloc(len + 1);
if (!new_contents) return NULL;
free(buf->contents);
buf->contents = new_contents;
}
memcpy(buf->contents, cstr, len + 1);
buf->length = len;
return buf;
}
Другие советы
Вы, кажется, не понимаете, что realloc
делает.
Как ты должен Подумайте об этом (по крайней мере, насколько она расширяется), состоит в том, что он выделяет новый буфер, копирует старые данные в него, а затем освобождает старый буфер.
Старый указатель тогда неверный И это не должно быть устойчивым, если вы получите сбой, когда вы попытаетесь использовать его снова позже.
Вы должны немедленно назначить возвращенное значение обратно в старый указатель, поэтому он все еще указывает на действительные данные.
Вы выделяете дополнительное пространство для строки в StringBuffer. Я просто предполагал, что содержимое Buf-> должно указывать на это дополнительное выделенное пространство. Если это не так, то почему дополнительное пространство выделено в StringBuffer?
Если Buf-> содержимое уже указывает в память, которая была выделена для StringBuffer, пытаясь Realloc он бросит систему памяти в аварию / виситель / поврежденную ситуацию кучи, потому что вы будете Realloc'ing указатель, который никогда не был выделен.
Вместо того, чтобы попытаться Realoc Buf-> содержимое, я думаю, что структура должна выглядеть как:
struct StringBuffer {
size_t length;
char contents[1];
};
Тогда вместо Reallocking Buf-> содержимое вы просто скопируете строку там, и Realloc для StringBuffer заботится обо всех памяти.