Проблема с Realloc () в C. всегда висит, но компилируется нормально

StackOverflow https://stackoverflow.com/questions/3137157

Вопрос

У меня проблемы с программой, которая предназначена для того, чтобы быть строковым буфером, в частности, эта функция предназначена для сброса буфера со строкой 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 заботится обо всех памяти.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top