Делает ли возврат указателя из функции перераспределение недействительным?

Итак, в настоящее время я пытаюсь написать программу на C для отслеживания самых длинных слов из argv. Все идет отлично! Пока я не попытался перераспределить двойной указатель символа, кажется, что это недопустимый указатель.

Точная ошибка, которую я получаю:

realloc(): invalid pointer
fish: Job 1, './longest-strings.o hello...' terminated by signal SIGABRT (Abort)

Я создаю этот двойной указатель символа через возврат функции, возможно, это ошибка? Я почти уверен, что использую realloc правильно, и я не могу отследить проблему.

Любая помощь будет принята с благодарностью!

/* 
 * Author: Smallblue2
 * Description: Program finds the longest word in an input string
 *
 * Input: A string from cmd line
 * Output: The longest word in a string
 */

// Header files
#include <stdio.h>
#include <stdlib.h>

// Function prototypes
int stringLength(char *string);
void longestWords(char **strings, int amt);
char **reset(char *string);
void display(char **longest, int len_array);

// Main function
int main(int argc, char **argv)
{
    char **strings = &*(argv + 1);
    longestWords(strings, argc - 1);
    return 0;
}

// Find the length of a string
int stringLength(char *string)
{
    int length = 0;
    while (*string != '\0')
    {
        length++;
        string++;
    }
    return length;
}

// Finds the longest word(s) from argv
void longestWords(char **strings, int amt)
{
    // Set up variables & pointers
    int len_array = 1;
    // Assign the first string to be the longest
    char **longest = reset(*(strings));
    int longest_len = stringLength(*(longest));
    int length = 0;
    // Loop through the rest of the strings
    for (int i = 1; i < amt; i++)
    {
        // Find the length of the current string
        length = stringLength(*(strings + i));
        // If it is larger, reset the longest array and place the
        // new string inside
        if (length > longest_len)
        {
            longest_len = length;
            longest = reset(*(strings + i));
            len_array = 1;
        // Else, expand the longest array's memory and add the
        // additional string inside
        } else if (length == longest_len) {
            len_array++;
            char **temp_longest = (char **)realloc(longest, len_array * sizeof(char *));
            if (!longest)
            {
                printf("Error: Memory allocation failed!\n");
                free(longest);
                return;
            }
            longest = temp_longest;
            *(longest + len_array - 1) = *(strings + i);
        }
    }
    // Display the longest word(s)
    display(longest, len_array);
    free(longest);
    longest = NULL;
    return;
}

// Resets the longest word array
char **reset(char *string)
{
    char **longest = (char **)malloc(sizeof(char *));
    if (!longest)
    {
        printf("Error: Memory Allocation Failed!\n");
        return NULL;
    }
    longest = &string;
    return longest;
}

// Displays the longest word(s)
void display(char **longest, int len_array)
{
    for (int i = 0; i < len_array; i++)
    {
        printf("%s\n", *(longest + i));
    }
    return;
}

Я пытался использовать как calloc, так и malloc, я пытался выполнить сценарий, в котором realloc не произойдет, а затем, по-видимому, free() также считает, что указатель недействителен. Здесь действительно потерялся.

Запустите свой код через valgrind. Если вы плохо управляете памятью, он скажет вам, где.

dbush 28.11.2022 01:41

В reset() вы возвращаете указатель на аргумент *string. Этот аргумент выходит за пределы области действия при возврате функции. В любом случае ваша программа segfaults в stringLength для меня, когда вы передаете указатель NULL.

Allan Wind 28.11.2022 01:43

Как только вы исправите это, я получаю sigabrt в longestWords, когда вы пытаетесь освободить самое длинное, поскольку это кадр стека, а не переменная, выделенная кучей

Allan Wind 28.11.2022 01:52
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вот два минимальных изменения:

  1. stringLength должен обрабатывать указатель NULL.
int stringLength(char *string)
{
    int length = 0;
    while (string && *string != '\0')
    {
        length++;
        string++;
    }
    return length;
}

Или, возможно:

#include <string.h>

size_t stringLength(char *string)
{
    return string ? strlen(string) : 0;
}
  1. reset() приводит к утечке памяти, которую вы только что выделили, и вы не хотите брать адрес аргумента, который находится вне области видимости, когда функция возвращается. Не совсем уверен, в чем смысл функции, но попробуйте вместо этого:
char **reset(char *string)
{
    char **longest = malloc(sizeof(char *));
    if (!longest)
    {
        printf("Error: Memory Allocation Failed!\n");
        return NULL;
    }
    *longest = string;
    return longest;
}

и пример вывода:

$ ./a.out hello...
hello...

./a.out hello world!
world!

Другие вопросы по теме