reallo c: неверная ошибка следующего размера, может кто-нибудь указать на ошибку, которую я сделал в распределении памяти - PullRequest
0 голосов
/ 14 января 2020

текст , который я передал функции get_document - это обычные строковые данные.

1. "" Обозначает разделение слов.

2 . "" обозначает разделение предложений.

3. "\ n" обозначает разделение абзацев.

get_document - это функция, которая выделяет каждое слово, предложение, абзац для отдельных блоков памяти. делая его легко доступным. Вот фрагмент кода.

char**** get_document(char* text) {
//get_document
int l=0,k=0,j=0,i=0;
char**** document = (char****)malloc(sizeof(char***));//para
document[l] = (char***)malloc(sizeof(char**));//sen
document[l][k] = (char**)malloc(sizeof(char*));//word
document[l][k][j] = (char*)malloc(sizeof(char));//letter

for(int z = 0; z < strlen(text); z++) {

    if(strcmp(&text[z]," ")==0) {
        document[l][k][j][i] = '\0';
        j++;
        document[l][k] = realloc(document[l][k],(sizeof(char*)) * j+1);
        i=0;
        document[l][k][j] = (char*)malloc(sizeof(char));
    }
    else if(strcmp(&text[z],".")==0) {
        k++;
        document[l] = realloc(document[l],(sizeof(char**)) * k+1);
        j=0;
        i=0;
        document[l][k] =(char**)malloc(sizeof(char*));
        document[l][k][j] = (char*)malloc(sizeof(char));
    }
    else if(strcmp(&text[z],"\n")==0) {
        l++;
        document = realloc(document,(sizeof(char***)) * l+1);
        k=0;
        j=0;
        i=0;
        document[l] = (char***)malloc(sizeof(char**));
        document[l][k] =(char**)malloc(sizeof(char*));
        document[l][k][j] = (char*)malloc(sizeof(char));

    }
    else {
        strcpy(&document[l][k][j][i],&text[z]);
        i++;
        document[l][k][j] = realloc(document[l][k][j],(sizeof(char)) * i+1);

    }

}
return document;

}

, но когда я запускаю программу, я получаю ошибку

reallo c: неверный следующий размер

Может кто-нибудь помочь мне с этим. Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 14 января 2020

при запуске программы выдается ошибка

reallo c: неверный следующий размер

Похоже, что один из Ваши realloc вызовы не выполняются, поскольку данные отслеживания распределителя были повреждены. Это одна из наиболее распространенных вещей, которые могут go ошибаться, когда вы перезаписываете границы объекта, особенно выделенного. Что вы делаете, много:

        strcpy(&document[l][k][j][i],&text[z]);

Если вы хотите добиться какого-либо прогресса в изучении C, важно, чтобы вы узнали разницу между char и строка. Строковые функции C, такие как strcmp() и strcpy(), применяются только к последним. Вы можете использовать их в пустых строках (содержащих только nul) или в односимвольных строках (содержащих один символ плюс nul ), среди других видов, но они не являются ни безопасными, ни полезными для отдельных char s. Для отдельных char вы вместо этого будете использовать стандартные операторы C, такие как == и =.

. В случае строки, указанной выше, каждый вызов strcpy будет пытаться скопировать весь хвост входной строки, включая терминатор, в одно-char -большое пространство, на которое указывает &document[l][k][j][i]. Это будет всегда записывать после конца выделенного пространства, часто много, что приводит к неопределенному поведению. Вместо этого вы хотите:

        document[l][k][j][i] = text[z];

( заслуженная критика в отношении выбора четверного указателя, оставленного в стороне). Я вижу, что вы оставляете добавление ограничителя строки на потом, что в принципе нормально, но я также вижу, что вы не можете завершить последнее слово каждого предложения, если точка ('.') следует сразу за словом без пробела.

В тех же строках несколько вариантов использования strcmp() каждый сравнивает весь хвост входной строки с одним из нескольких строковых литералов длины одна. Такие сравнения разрешены, но они не дадут желаемых результатов. Похоже, вам нужны простые тесты на равенство с символьными константами, вместо этого:

    if (text[z] == ' ')
    // ...
    else if (text[z] == '.')
    // ...
    else if (text[z] == '\n')

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

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

0 голосов
/ 14 января 2020

Вы путаете символы со строками.


Ваши условия обнаружения ваших элементов неверны:

if(strcmp(&text[z]," ")==0)
else if(strcmp(&text[z],".")==0)
...

Если strlen(text) == 1, вы никогда не войдете ни в одну из своих ветвей. strcmp сравнивает строки, а не отдельные символы. Это означает, что он сравнивает весь оставшийся буфер со строкой длины 1, которая никогда не может быть истинной, за исключением последнего символа. Если вы хотите сравнить отдельные символы, используйте if(text[z] == ' ').


В вашей последней ветке else вы полностью sma sh ваша куча:

strcpy(&document[l][k][j][i],&text[z]);

Вы копируете строку (снова: полный оставшийся буфер) в один символ , Память для document[l][k][j] была выделена с помощью size=1. Это даже не может содержать строку длины 1, потому что нет места для завершения '\0' байта.

Копирование строки в память, достаточно большую, чтобы вместить ровно 1 символ, вызывает повреждение кучи и при любом вызове выделения памяти Эта функция, наконец, будет взорвана, как вы видите в сообщении об ошибке.

Что вам нужно:

document[l][k][j][i] = text[z];
document[l][k][j][i+1] = 0;

Наконец, ваш объем памяти для выделения неправильный:

document = realloc(document,(sizeof(char***)) * l+1);

Вы хотите добавить 1 дополнительный элемент в массив, но вы добавляете только 1 байт. Используйте это вместо:

document = realloc(document,(sizeof(char***)) * (l+1));

То же самое относится ко всем остальным уровням вашей конструкции.


Кроме того, ваше наименование счетчиков плохое. Однозначные имена переменных должны использоваться только для циклов и т. Д. c. там, где нет риска путаницы. Если вы используете их для разных уровней индексации массива, вы должны использовать такие имена, как wordcount, paracount et c. Это сделает код намного более читабельным.

Также я предлагаю вам следовать подсказкам в комментариях. Пересмотрите свой полный дизайн.

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