SegFault при использовании std :: string :: operator + = с функцией в качестве параметра

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

#include <iostream>
using namespace std;

const char *hex(char);

int main(int argc, char **argv)
{
    string url = "start http://www.cplusplus.com/search.do?q = ";
    char a[2];

    for (int i = 0; i < argc; i++)
    {
        if (i != 1)
            url += '+';
        for (int j = 0; argv[i][j]; j++)
        {
            if (i == 1 && j == 0 && argv[i][j] == '.')
                continue;
            url += '%';

            // a[0] = argv[i][j] / 16;
            // a[1] = argv[i][j] % 16;
            // for (int k = 0; k < 2; k++)
            // {
            //  if (a[k] > 9)
            //      a[k] += 'A' - 10;
            //  else
            //      a[k] += '0';
            //  url += a[k];
            // }

            url += hex(argv[i][j]);
        }
    }
    system(url.c_str());
    return 0;
}

const char *hex(char c)
{
    char h = {c / 16, c % 16, '\0'};
    for (int k = 0; k < 2; k++)
        if (h[k] > 9)
            h[k] += 'A' - 10;
        else
            h[k] += '0';
    return h;
}

Но для этого фрагмента кода, который, как ожидается, будет работать как команда для URL-кодирования переданных аргументов, есть проблема с оператором + = для строкового класса. Я следил за ним в отладчике, и функция hex работает правильно (возвращает hexValue of char c).

Но в этой строке url += hex(argv[i][j]); по какой-то причине есть segFault, argv [i] [j] - это char, а hex () возвращает его шестнадцатеричное значение в виде const cstring (const char *). Я даже добавил нулевой символ в конце, если это имело значение ...

Я даже проверил ссылку std :: string, чтобы убедиться, что оператор принимает const char * (но это очевидно, иначе были бы ошибки Compile-t, которых у меня не было).

Есть догадки? Кстати, закомментированный код заменяет код функционального стиля и работает безупречно, конечно, в Windows.

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

Часть «какая-то причина» - это то, почему вы бросаете это в свой отладчик, чтобы точно узнать, где он падает, затем запускаете его снова и осторожно переходите к этому моменту, наблюдая за поведением вашего кода и состоянием любых соответствующих переменных.

tadman 17.10.2018 19:15

Меня действительно смущает ваша реализация hex. Заявлено, что он возвращает const char*, но вы возвращаете char. Char h инициализируется списком инициализаторов, как если бы он был массивом. Я удивлен, что это, по-видимому, компилируется. Вы отключили предупреждения компилятора?

alter igel 17.10.2018 19:17

Действительно, ваша функция hexне компилируется.

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

Ответы 1

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

Ваша функция hex возвращает адрес временной локальной переменной, что является огромной проблемой, поэтому она дает сбой при повторном использовании этой памяти.

Когда эта функция возвращает, h выпадает из области действия немедленно, поэтому любые указатели на h становятся недействительными.

Поскольку вы используете C++, просто используйте std::string:

std::string hex(const char c)
{
    std::string h = {c / 16, c % 16, '\0'};

    for (int k = 0; k < 2; k++)
        if (h[k] > 9)
            h[k] += 'A' - 10;
        else
            h[k] += '0';

    return h;
}

Также вместо того, чтобы изобретать колесо, подумайте об использовании таких вещей, как std::hex, чтобы сделать это за вас как показано здесь.

Итак, означает ли это, что невозможно вернуть cstring из функции C++? Я запутался. Я только новичок и хочу понять основы, пробуя такие глупые вещи, как эти

makeway4pK 17.10.2018 19:29

@ user10519731 это вполне возможно, поскольку C++ в основном является надмножеством C. Однако строки в стиле C заставляют задуматься о времени жизни, владении и управлении ресурсами. std::string C++ можно использовать просто, безопасно и правильно, не задумываясь ни о чем из этого.

alter igel 17.10.2018 19:30

Вы можете вернуть строку если и только если в стиле C, которую вы динамически выделяете (например, malloc), либо она существовала, либо ей иным образом назначена функция до. Если вы распределяете динамически, то ответственность за ее освобождение в конечном итоге несет вызывающая функция (например, free). Поскольку C заставляет вас понимать управление памятью на очень низком уровне, обычно лучше всего этого избегать и по возможности использовать контейнеры C++, такие как std::vector и std::string. Их обычно быстро и дешево копировать, и они могут использовать ссылки для оптимизации хранения и сохранения данных.

tadman 17.10.2018 19:33

@DanielSchepler Технически верно, но и очень опасно. Некоторые знания следует сохранять и не распространять до тех пор, пока они не станут абсолютно необходимыми.

tadman 17.10.2018 20:06

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