Обнаружено разрушение стека при копировании двоичного файла в C - PullRequest
0 голосов
/ 28 января 2019

ОБНОВЛЕНИЕ ВНУТРИ ====

Некоторое время назад я сделал следующую функцию, которую я успешно использовал для получения значений серого из изображений ( wxh измерение), которые были преобразованыв .bin-файлы.Это просто дает массив всех значений пикселей. Однако это была не такая функция, а немедленная вставка в main ().

// read the BIN-file as grayscale image
void decodeBIN(const char* filename, short image[], int w, int h){
    int i = 0;
    unsigned char buffer[16]; // no specific size attributed
    FILE *ptr;

    ptr = fopen(filename, "rb");
    if (!ptr){
        printf("\nUnable to open file!\n"); // error
    }

    while (!feof(ptr)){
        fread(buffer,2,1,ptr); // read w bytes to buffer
        image[i] = buffer[1];
        //printf("%u ", image[i]); // DEBUG
        i++;
    }
    fclose(ptr);
    printf("\nBinary image read (npixels: %i).\n", i-1); // DEBUG
}

Я решил расширить код, поэтому переписал его в предыдущую функцию.и поместил его в отдельный файл для функций, а также сделал заголовочный файл.Дополнительный файл для функций и заголовочный файл работают на 100%, так что это не проблема.Теперь этот код больше не работает, и я получаю ошибку разрушения стека.Некоторые переменные, вызванные после этой функции, также перешли на другое значение, поэтому я решил, что проблема связана с буфером (я не знал о правильном размере буфера, но он работал ...).После некоторых экспериментов и испытаний я придумал следующую функцию.Я заменил буфер на массив символов с именем image2, чтобы просто попробовать и протестировать его:

void decodeBIN(const char* filename, short image[], int w, int h){
    int i = 0, res;
    char image2[];
    FILE *ptr;

    ptr = fopen(filename, "rb"); //"MySnap_20180327-2239-010.bin"
    if (!ptr){
        printf("\nUnable to open file!\n"); // error
    }

    res = fread(image2,1,w*h,ptr) // need to read w*h pixels

    while (i < w*h){ // DEBUG
        printf("%i ", (int)image2[i]); // DEBUG
        i++;
    }
    printf("\nRead %u bytes\n", res); // DEBUG
    fclose(ptr);
    printf("Binary image read (npixels: %i).\n", i); // DEBUG
}

Я немного растерялся, как он работал, и внезапно, когда я перемещаю код из main() для функции, которая перестает работать, поэтому любая помощь приветствуется!

Заранее спасибо.

Отказ от ответственности: Я намерен написать это с помощью как можно меньшего количества библиотек

===== ОБНОВЛЕНИЕ:

После ответа @alainmerigot я получил этот код, который помог получить правильные значения:

void decodeBIN(const char* filename, unsigned char image[], int w, int h){
    int i = 0, res;
    FILE *ptr;

    res = fread(image,sizeof(char),w*h,ptr) // need to read w*h pixels
    fclose(ptr);
}

Ошибка сегментации иПерескоченные переменные все еще на месте, так что здесь более подробный обзор того, что я делаю:

char filenamePathed["[path of file]/file.bin"];
short img1[npixels]; // npixels = w*h
printf("i_file: %i\n", i_file); // correct value
decodeBIN(filenamePathed, img_curr, w, h); // decode bin
printf("i_file: %i\n", i_file); // value jumped
while (i < npixels){
    img1[i] = (short)img_curr[i];
    i++;
}

Возможно, это хорошо, что я делаю это итеративно для нескольких файлов (времясерии)?Мне также нужно, чтобы он получился в (коротком) формате (или целочисленном), но в конечном итоге он должен быть эффективным с точки зрения памяти, а пиксели имеют диапазон 0-255, так что int немного обилие imo).

Ответы [ 2 ]

0 голосов
/ 29 января 2019

Видимо, проблема была с выделением image, хотя я не уверен, почему это было неправильно.Раньше я выделял его на unsigned char image[npixels];, и решение этой ошибки оказалось unsigned char image[npixels*7]; Каким-то образом это работает, но если у кого-то есть объяснение, сделайте это:)

0 голосов
/ 28 января 2019

Проблема с вашей второй функцией заключается в том, что вы пишете в массиве image2, пока для него не было зарезервировано места.Объявление char image2[]; говорит только о том, что массив существует и что адрес этого массива можно найти в var image2, но с ним не связано ни одного пробела, поэтому проблема.

С этим можно связать пространствомассив несколькими способами.

Использование постоянного хранилища в куче

image2 = malloc(x*y); // but do not forget to free(image2) at the end of the function

Использование временного хранилища в стеке (пространство автоматически освобождается при выходе из функции).

image2 = alloca(x*y); // slightly faster than malloc and do not require to free() the image

Но лучше всего использовать массив с параметризованным размером (начиная с C99).Ваш массив должен быть объявлен как

char image2[w*h]; // will use the value of w and h to define array size

Если вы хотите сделать что-то иное, чем печать значений изображения в вашей функции, вы должны сохранить изображение в постоянной памяти и иметь возможностьзнать адрес массива в вашей программе.Вероятно, это именно то, что вы хотели, и именно поэтому в вашем списке параметров есть short image[].

Решение состоит в том, чтобы просто использовать image вместо image2 в fread().

Но объявление image должно быть согласованным, а изображение должно быть массивом char, а не short.

Остерегайтесь также объявлений.В первой функции изображение представляет собой массив unsigned char, а во второй - массив char.Хотя размер хранилища одинаков и fread() будет хранить одинаковые значения, они не эквивалентны.Если используется в арифметическом контексте, image[i] будет интерпретироваться по-разному, и результаты, вероятно, будут отличаться.В общем, изображения unsigned.

...