#arrays #c #pointers
Вопрос:
Я просматривал Начало C, Пятое издание, и в настоящее время я нахожусь в главе 7, которая посвящена указателям. Я попытался запустить пример, который был приведен в этой главе, но я сталкиваюсь с realloc(): invalid next size
ошибкой, когда массив выходит за пределы 6 элементов. Вот код, который в основном скопирован и вставлен из книги:
// Program 7.14 Using array notation with pointers to sort strings
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define BUF_LEN 100 // Length of input buffer
#define COUNT 5 // Initial number of strings
int main(void)
{
char buf[BUF_LEN]; // Input buffer
size_t str_count = 0; // Current string count
size_t capacity = COUNT; // Current maximum number of strings
char **pS = calloc(capacity, sizeof(char*)); // Pointers to strings
char** psTemp = NULL; // Temporary pointer to pointer to char
char* pTemp = NULL; // Temporary pointer to char
size_t str_len = 0; // Length of a string
bool sorted = false; // Indicated when strings are sorted
printf("Enter strings to be sorted, one per line. Press Enter to end:n");
// Read in all the strings
char *ptr = NULL;
while(true)
{
ptr = fgets(buf, BUF_LEN, stdin);
if(!ptr) // Check for read error
{
printf("Error reading string.n");
free(pS);
pS = NULL;
return 1;
}
if(*ptr == 'n') break; // Empty line check
if(str_count == capacity)
{
capacity = capacity/4; // Increase capacity by 25%
if(!(psTemp = realloc(pS, capacity))) return 1;
pS = psTemp;
}
str_len = strnlen(buf, BUF_LEN) 1;
if(!(pS[str_count] = malloc(str_len))) return 2;
strcpy(pS[str_count ], buf);
}
// Sort the strings in ascending order
while(!sorted)
{
sorted = true;
for(size_t i = 0 ; i < str_count - 1 ; i)
{
if(strcmp(pS[i], pS[i 1]) > 0)
{
sorted = false; // We were out of order so. . .
pTemp= pS[i]; // swap pointers pS[i]. . .
pS[i] = pS[i 1]; // and. . .
pS[i 1] = pTemp; // pS[i 1]
}
}
}
// Output the sorted strings
printf("Your input sorted in ascending sequence is:nn");
for(size_t i = 0 ; i < str_count ; i)
{
printf("%s", pS[i]);
free(pS[i]); // Release memory for the word
pS[i] = NULL; // Reset the pointer
}
free(pS); // Release the memory for pointers
pS = NULL; // Reset the pointer
return 0;
}
Ошибка возникает в этой строке:
if(!(psTemp = realloc(pS, capacity))) return 1;
Кроме того, я говорю, что код «в основном» скопирован, потому что код из книги использует функции C11, такие как strnlen_s
и strcpy_s
к которым у меня нет доступа. Я использую strnlen
и strcpy
вместо этого. Я не уверен, что это то, что вызывает проблему. Однако вот дословный код из книги:
// Program 7.14 Using array notation with pointers to sort strings
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define BUF_LEN 100 // Length of input buffer
#define COUNT 5 // Initial number of strings
int main(void)
{
char buf[BUF_LEN]; // Input buffer
size_t str_count = 0; // Current string count
size_t capacity = COUNT; // Current maximum number of strings
char **pS = calloc(capacity, sizeof(char*)); // Pointers to strings
char** psTemp = NULL; // Temporary pointer to pointer to char
char* pTemp = NULL; // Temporary pointer to char
size_t str_len = 0; // Length of a string
bool sorted = false; // Indicated when strings are sorted
printf("Enter strings to be sorted, one per line. Press Enter to end:n");
// Read in all the strings
char *ptr = NULL;
while(true)
{
ptr = fgets(buf, BUF_LEN, stdin);
if(!ptr) // Check for read error
{
printf("Error reading string.n");
free(pS);
pS = NULL;
return 1;
}
if(*ptr == 'n') break; // Empty line check
if(str_count == capacity)
{
capacity = capacity/4; // Increase capacity by 25%
if(!(psTemp = realloc(pS, capacity))) return 1;
pS = psTemp;
}
str_len = strnlen_s(buf, BUF_LEN) 1;
if(!(pS[str_count] = malloc(str_len))) return 2;
strcpy_s(pS[str_count ], str_len, buf);
}
// Sort the strings in ascending order
while(!sorted)
{
sorted = true;
for(size_t i = 0 ; i < str_count - 1 ; i)
{
if(strcmp(pS[i], pS[i 1]) > 0)
{
sorted = false; // We were out of order so. . .
pTemp= pS[i]; // swap pointers pS[i]. . .
pS[i] = pS[i 1]; // and. . .
pS[i 1] = pTemp; // pS[i 1]
}
}
}
// Output the sorted strings
printf("Your input sorted in ascending sequence is:nn");
for(size_t i = 0 ; i < str_count ; i)
{
printf("%s", pS[i]);
free(pS[i]); // Release memory for the word
pS[i] = NULL; // Reset the pointer
}
free(pS); // Release the memory for pointers
pS = NULL; // Reset the pointer
return 0;
}
Я просмотрел множество сообщений о StackOverflow и других местах, которые помогли мне понять, что происходит не так, но я не смог этого понять. Я также использовал gdb и valgrind, чтобы попытаться диагностировать проблему, но я также не смог извлечь много информации из этих инструментов. Хотя я довольно неопытен в них, особенно в вальгринде.
Я думаю, что мне просто не хватает чего — то маленького. Вот пример запуска программы с вводом, взятым из книги:
Enter strings to be sorted, one per line. Press Enter to end:
Many a mickle makes a muckle.
A fool and your money are soon partners.
Every dog has his day.
Do unto others before they do it to you.
A nod is as good as a wink to a blind horse.
The bigger they are, the harder they hit.
Least said, soonest mended.
realloc(): invalid next size
signal: aborted (core dumped)
Независимо от того, какой ввод, я получаю эту ошибку после 7 строк.
Любая помощь в этом будет весьма признательна. Заранее спасибо!
Комментарии:
1. Подобная ошибка обычно возникает, когда вы выходите за пределы выделенной памяти перед вызовом
realloc
. Например, если вы выделяете мало памяти, что вы делаете вrealloc
вызовах (размер для перераспределения-это количество выделяемых байтов , а не количество «элементов»).2. Я почти уверен, что вы не скопировали пример дословно. Ты должен сделать это первым. Почему у вас нет доступа к функциям C11? Что мешает вам использовать не древний компилятор, совместимый с C11?
3. Спасибо всем за комментарии, решение @user3121023 устранило проблему для меня. Должен ли я ответить на свой собственный вопрос решением?
4. @SergeyA Я использую онлайн-компилятор на Replit для запуска кода, и я предполагаю, что у компилятора там нет функций C11. Я также отредактировал вопрос, включив в него код, взятый дословно из книги.
5. @amehdi96 вы можете использовать любой другой онлайн-компилятор, который поддерживает C11, например coliru.stacked-crooked.com
Ответ №1:
Благодаря предложению пользователя 3121023 я решил эту проблему, изменив эту строку:
if(!(psTemp = realloc(pS, capacity))) return 1;
к этому:
if(!(psTemp = realloc(pS, capacity * sizeof(*pS)))) return 1;
Причина этого в том, что я должен выделить количество байтов, а не количество элементов. Я не уверен, почему в книге все было неправильно, но я думаю, что это более раннее издание, поэтому, вероятно, оно исправлено в более позднем издании.