Выделение пространства и объединение в массив символов без знака в c

#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. Спасибо! Я никогда не был очень силен в выделении памяти и никогда не был уверен, правильно ли я это сделал. Кроме того, я знаю, что я предполагаю выделить отдельный указатель и выполнить проверку ошибок — просто хотел сохранить его чистым и простым.