Сомнение в распределении памяти с указателем типа на символ - PullRequest
0 голосов
/ 27 сентября 2011

Предполагается, что эта программа запрашивает количество букв в слове (будет введено позже), поэтому она знает, сколько места нужно выделить.Кажется, все работает нормально, однако не имеет значения, выделяете ли вы меньше памяти, чем необходимо для хранения слова.Это ошибка, которую я должен исправить, или это потому, что так работает указатель на char (char *)?

#include <stdio.h>
#include <stdlib.h>

int main() 
{
unsigned int a = 0;
printf("Enter the size of the word(0=exit) :");
scanf("%d",&a);
if(a==0){return 0;}
else
     {
      char *word = (char *)malloc(a*sizeof(char) + 1);
      if(word == NULL)
          {
           fprintf(stderr,"no memory allocated");
           return 1;
          }
      printf("Reserved %d bytes of space (accounting for the end-character).\nEnter your word: ", a*sizeof(char) + 1);
      scanf("%s", word);
      printf("The word is: %s\n", word);
     }

return 0;
}

Хорошо, я думаю, что я мог бы это исправить, так как работа с valgrind не показывает ничегоиз ошибок, которые он показал ранее.

char aux[]="";
  scanf("%s", aux);

  if(strlen(aux)>(a*sizeof(char) + 1))
     {
  fprintf(stderr,"Word bigger than memory allocated\nExiting program\n");
  return 1;
     }
  else
     {
      strcpy(word,aux);
      printf("The word is: %s\nAnd is %d characters long\n", word, strlen(word));
     }

Теперь я сомневаюсь: почему я могу объявить пустой массив символов (char aux [] = ""), а затем использовать «лишнюю» память без ошибок(в выводе valgrind) все еще char * aux = "";дает мне ошибку сегментации?Я очень новичок в программировании на C, поэтому прошу прощения, если это очевидный / тупой вопрос.Спасибо.

Ответы [ 3 ]

1 голос
/ 27 сентября 2011

Это не имеет значения, но это делает , если вы используете больше места, чем выделено, вы в конечном итоге закончите переполнением буфера. Возможно, что ваша текущая реализация выделяет немного больше, чем вы на самом деле запрашиваете, также возможно, что это не так. Вы не можете передать это поведение, никогда не обращайтесь к / не используйте память, которая не была выделена.

Также sizeof( char ) == 1 по определению.

1 голос
/ 27 сентября 2011

Да, вы должны исправить эту ошибку в вашей программе.

Когда вы выделяете меньше памяти, чем вам нужно, и позже получаете доступ к этой «дополнительной» памяти, программа переходит в неопределенное поведение Режим.Может показаться, что это работает, или может произойти сбой, или это может сделать что-то неожиданное.По сути, ничего гарантируется после записи в дополнительную память, которую вы не выделили.

[Обновление:]

Мое предложение прочитать строку произвольной длиныиз файла следующий код.Я не могу смириться с тем, что он несколько длинный, но так как стандартный C не обеспечивает хороший тип строковых данных, мне пришлось самому заняться управлением памятью.Итак, вот оно:

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/** Reads a string from a file and dynamically allocates memory for it. */
int fagetln(FILE *f, /*@out*/ char **s, /*@out*/ size_t *ssize)
{
  char *buf;
  size_t bufsize, index;
  int c;

  bufsize = 128;
  if ((buf = malloc(bufsize)) == NULL) {
    return -1;
  }

  index = 0;
  while ((c = fgetc(f)) != EOF && c != '\n') {
    if (!(index + 1 < bufsize)) {
      bufsize *= 2;
      char *newbuf = realloc(buf, bufsize);
      if (newbuf == NULL) {
        free(buf);
        return -1;
      }
      buf = newbuf;
    }
    assert(index < bufsize);
    buf[index++] = c;
  }

  *s = buf;
  *ssize = index;
  assert(index < bufsize);
  buf[index++] = '\0';
  return ferror(f) ? -1 : 0;
}

int main(void)
{
  char *s;
  size_t slen;

  if (fagetln(stdin, &s, &slen) != -1) {
    printf("%zu bytes: %s\n", slen, s);
  }
  return 0;
}
0 голосов
/ 27 сентября 2011

Обычно (но не всегда) переполнения выделенных буферов вызывают сбой при free буфере.Если вы добавите free(word) в конце, вы, вероятно, увидите сбой.

...