У меня проблема с выделением памяти. (Возможно) - PullRequest
0 голосов
/ 08 апреля 2019

есть входной файл;несортированные длинные номера. (около 1 миллиона) Я хочу отсортировать числа во входных файлах.Чтобы выделить память для массива, я использовал fseek и ftell.Но ошибка сегментации произошла.Как мне исправить код?

int main( int argc, char *argv[] )
{
    long *arr;
    FILE *fp = NULL;
    FILE *fp2 = NULL;
    int   i = 0;
    long  size, count;

    fp  = fopen( "argv[1]", "r" );
    fp2 = fopen( "sorted",  "w" );
    if ( fp == NULL || fp2 == NULL )
        printf( "error \n" );
    else
    {
        fseek( fp, 0, SEEK_END );
        size = ftell( fp );
        arr = ( long * ) malloc( size );
        count = fread( arr, size, 4, fp );

        Quicksort( arr, 0, sizeof( arr ) / sizeof( int ) - 1 );

        while ( i != ( sizeof( arr ) / sizeof( int ) - 1 ) )
        {
            int i = 0;
            int j;
            for ( j = 0; j < 5; j++ )
                fwrite( arr, size, 1, fp2 );
        }
    }
    fclose( fp );
    free( arr );
    fclose( fp2 );
    return 0;
}

Ответы [ 3 ]

4 голосов
/ 08 апреля 2019

Проблема заключается в том, что код находит число байтов в файле с ftell(), а затем выделяет любое size количество данных.

Однако при чтении из файла он пытается прочитать в четыре раза больше данных из-за переданных количества элементов и размера элементов . до fread().

Если входной файл представлял собой большой блок двоичных длин (в том же формате, что и локальное оборудование), можно просто fread() много за один раз. Это означает, что ваш размер равен ftell(), но количество элементов равно one .

fseek( fp, 0, SEEK_END );
size = ftell( fp );
arr = ( long * ) malloc( size );
count = fread( arr, size, 1, fp );  // read the whole block in a single go
3 голосов
/ 08 апреля 2019

Есть куча вещей, на которые нужно обратить внимание без особого порядка серьезности

  • всегда проверять аргументы

ваша программа, похоже, не проверяет аргументы, что является своего рода плохим, быстрое утверждение в начале сделает эту работу

 /* Always do some argument checking, Assuming in your case command line is 2 */
    if ( argc != 2 ) 
    {
        printf("Invalid arguments ");
        printf("Usage %s <filename>\n", argv[0]);
        exit(0);
    }
  • всегда проверять возвращаемые значения

Почти всегда хорошая идея проверять возвращаемые значения и проверять их, конечно, есть, например, некоторые исключения printf, но в таких случаях, как fopen, malloc преступление не проверять возвращаемые значения

/* Return Type Validations are mandatory */
    fp  = fopen( argv[1], "r" );
    if( fp == NULL )
    {
        printf("Error Opening file %s\n", argv[1]);
        exit(0);
    }
  • Не приводить результат malloc

Это популярный Я разыграю результат malloc Ответ -

  • fread

Это, вероятно, из-за неправильного понимания поведения функции, от man fread

The function fread() reads nmemb items of data, each size bytes long,
       from the stream pointed to by stream, storing them at the location
       given by ptr.

вы, по сути, в четыре раза читаете данные, которые вам нужны, написав заявление типа

count = fread( arr, size, 4, fp );
  • смешивание local и global области применения

    Существует несколько объявлений переменной i в локальном (внутри for loop), и глобальная область не делает этого.

  • Осторожно при использовании sizeof() для понитеров

этот оператор sizeof( arr ) всегда дает размер указателя, а не размер данных, на которые указывает указатель, приведенный ниже оператор

Quicksort( arr, 0, sizeof( arr ) / sizeof( int ) - 1 );

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

3 голосов
/ 08 апреля 2019

Здесь много проблем, и я думаю, что это даже не настоящий код. Из них сразу заметно:

  • вы пытаетесь открыть файл с именем argv[1], а не имя файла, указанное в командной строке. Бросьте цитаты.

  • Вы выделяете память для size байтов, затем пытаетесь прочитать size * 4 байтов и не проверяете, сколько было прочитано

  • не приведено возвращаемое значение malloc

  • sizeof arr дает вам только размер указателя, а не данные, которыми вы располагаете. У вас есть size, используйте его.

  • ваш цикл while имеет новую переменную с тем же именем, что и снаружи, и никогда не изменяется, поэтому цикл вечен

  • если вы не можете открыть файл, вы освобождаете неназначенный указатель

Так что проверьте предупреждения вашего компилятора. Подумайте о том, что вы делаете, что означают параметры, которые вы даете функциям. Проверьте возвращаемые значения. Используйте отладчик для пошагового выполнения кода.

Точная причина может быть определена только после того, как вы исправите другие проблемы, и может даже быть исправлена ​​этим. Если это точный код, то причина, вероятно, в последнем. Отладчик скажет вам.

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