#c #realloc
#c #перераспределение
Вопрос:
Я создаю компрессор изображений для проекта. Я генерирую коды для значений в изображении таким образом, чтобы для каждого значения серого цвета (от 0-254) в массиве с именем codeArray был код char * (кодировка Хаффмана).
Обязательным требованием является наличие функции, которая возвращает символ без знака * . Я просматриваю каждый пиксель и преобразую серое значение этого пикселя в код, используя codeArray .
Мне нужно, чтобы массив символов без знака динамически увеличивался по мере преобразования большего количества значений серого и объединения в конец массива.
unsigned char* encodedString = malloc(sizeof(char));
int width = image->width; //width and height of image structure
int height = image->height;
int row, col;
for(row = 0; row<height; row )
for(col = 0; col<width; col )
{
int value = image->pixel[row][col]; //gets the grey value
encodedString = realloc(encodedString, (strlen(encodedString) strlen(codeArray[value])));
strcat(encodedString, codeArray[value]);
}
Я попытался запустить это с помощью инструкции print после strcat и обнаружил, что он печатается до тех пор, пока не наберется 24 символа, затем начал печатать мусор, а затем произошел сбой Seg.
Помощь приветствуется!
Ответ №1:
Вы вызываете strlen(encodedString)
неинициализированный буфер. Это неопределенное поведение. Вам необходимо обнулить начальное содержимое encodedString
.
unsigned char* encodedString = malloc(1);
//check for malloc errors
encodedString[0] = '';
Похоже, вам сойдет с рук эта ошибка, но затем немедленно зафиксируйте другую. Вы realloc
освобождаете место для strlen(encodedString) strlen(codeArray[value])
, но вы забыли выделить место для нулевого терминатора. Предположительно, это то, что вызывает strcat
бомбу. Исправьте эту проблему, добавив единицу к параметру size to realloc
.
Как указывает @Lou, производительность вашей стратегии перераспределения может быть низкой. Возможно, вам лучше выделить буфер один раз в начале функции, поскольку, предположительно, вы можете установить относительно жесткую верхнюю границу его размера.
И вы также никогда не должны писать ptr = realloc(ptr, ...)
, поскольку вы не сможете восстановиться после сбоя realloc
и всегда будете протекать. Но это действительно нюанс по сравнению с другими ошибками.
Комментарии:
1. 1. Более или менее мое наблюдение, за исключением того, что мне нравится проповедовать
realloc
опасности при каждой возможности 😉2. @David — Не говоря уже об эффективности вызова realloc() один раз для каждого значения, которое вы добавляете к закодированной строке. Либо вычислите, сколько места вам понадобится, и выделите его заранее, либо, по крайней мере, используйте некоторый двоичный рост encodedString (т. Е. удваивайте размер массива encodedString каждый раз, когда вам нужно увеличить размер).
3. @larsmans re. перераспределение, я знаю, что ты имеешь в виду, но я вроде как чувствовал, что основной упор должен быть сделан на более вопиющие ошибки. Каждый вопрос такого рода заставляет меня еще больше ценить преимущества языков с реальными строковыми типами данных.
4. Спасибо! Я никогда не был очень силен в выделении памяти и никогда не был уверен, правильно ли я это сделал. Кроме того, я знаю, что я предполагаю выделить отдельный указатель и выполнить проверку ошибок — просто хотел сохранить его чистым и простым.