Почему этот код падает при динамическом размещении? - PullRequest
0 голосов
/ 05 июня 2009

У меня есть этот фрагмент кода ниже, и он падает при назначении в 'str', динамическое выделение.

  char *str;
  int file_size;
  FILE *fptr;
  if (!(fptr = fopen(filename, "r"))) goto error1;
  if ((fseek(fptr, 0L, SEEK_END) != 0)) goto error2;
  if (!(file_size=ftell(fptr))) goto error2;
  if ((fseek(fptr, 0L, SEEK_SET) != 0)) goto error2;
  str =  (char*)malloc(file_size+1);
  if (fread(str, file_size, 1, fptr) != 1) {
    free(str);
    goto error2;
  }
  str[file_size] = '\0';
  fclose(fptr);

file_size является ненулевым, неотрицательным значением меньше 140

Я использую ARM. На самом деле это работает на моем компьютере Intel, но не на ручном компьютере.

Ответы [ 7 ]

7 голосов
/ 05 июня 2009

Вы можете увидеть это в руководстве - ftell () возвращает -1 при ошибке, а не ноль.

3 голосов
/ 05 июня 2009

Распечатайте ваши переменные, в частности file_size, перед их использованием. Вы можете получить сюрприз.

2 голосов
/ 05 июня 2009

malloc ожидает size_t для аргумента. size_t - это typedef для unsigned int или unsigned long (в зависимости от платформы), ключ здесь UNSIGNED.

Вы используете int для file_size, и int может быть ПРОСТО 16 бит (вы используете ARM, поэтому я подумаю, что это MCU). Знаковые 16 бит могут поддерживать только 32 768 байт размера файла в байтах, поэтому, если у вас большой файл (на самом деле не такой большой, просто> 32 КБ), file_size будет переполнен.

Я думаю, что вам это сказал компилятор, но вы решили проигнорировать его ... теперь Мэллов принимает беззнаковый аргумент, поэтому он автоматически приводит вашу подписанную оценку размера файла + 1 (даже если он сильно переполнен, подписанный большой отрицательный знак времени ) и пытается выделить память. Это может означать, что вы пытались выделить слишком много памяти, чем это встроенное приложение. не мог иметь (не должен был разбиться).

На самом деле я не вижу причины сбоя (кроме плохой библиотеки, которая во встроенном C является распространенной из-за низкой обратной связи с пользователями), но я вижу ошибки, которые приводят к нежелательному поведению.

Я даже не пойду и не спрошу: «Почему все пошло?», Потому что ответ вызвал бы много пламенных комментариев.

2 голосов
/ 05 июня 2009

Какое значение возвращает ftell(fptr)? Может быть, он слишком большой? Если он возвращает long int действительно , то он может переполнить ваш int, и вы получите там отрицательное значение.

1 голос
/ 05 июня 2009

где-нибудь до того, как вы переполните буфер ИЛИ освободите () по неправильному адресу !!! -)

0 голосов
/ 05 июня 2009

Вряд ли это ваша проблема, но вы не забыли

#include <stdlib.h>

так что прототип malloc находится в области видимости? Компилятор не будет предупреждать вас в этом случае из-за случайного приведения его возвращаемого значения. В C нет причин приводить возвращаемое значение malloc. Итак:

str =  malloc(file_size + 1);

Кстати, пробелы свободны.

Наконец, вы должны открыть файл в двоичном режиме, если хотите иметь возможность определять его размер таким образом на нескольких платформах.

На основании:

str[file_size] = '\0';

вы, похоже, неявно предполагаете, что файл не может содержать вложенные символы \ 0. Это кажется мне опасным предположением, если вы действительно делаете это.

0 голосов
/ 05 июня 2009

В общем смысле ... Я вовсе не собираюсь использовать bash, но ваш код немного ужасен. Использование стандартов кодирования обычно проясняет ситуацию ... Тем не менее, Нил, вероятно, получил ответ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...