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





Ваша функция 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++? Я запутался. Я только новичок и хочу понять основы, пробуя такие глупые вещи, как эти
@ user10519731 это вполне возможно, поскольку C++ в основном является надмножеством C. Однако строки в стиле C заставляют задуматься о времени жизни, владении и управлении ресурсами. std::string C++ можно использовать просто, безопасно и правильно, не задумываясь ни о чем из этого.
Вы можете вернуть строку если и только если в стиле C, которую вы динамически выделяете (например, malloc), либо она существовала, либо ей иным образом назначена функция до. Если вы распределяете динамически, то ответственность за ее освобождение в конечном итоге несет вызывающая функция (например, free). Поскольку C заставляет вас понимать управление памятью на очень низком уровне, обычно лучше всего этого избегать и по возможности использовать контейнеры C++, такие как std::vector и std::string. Их обычно быстро и дешево копировать, и они могут использовать ссылки для оптимизации хранения и сохранения данных.
@DanielSchepler Технически верно, но и очень опасно. Некоторые знания следует сохранять и не распространять до тех пор, пока они не станут абсолютно необходимыми.
Часть «какая-то причина» - это то, почему вы бросаете это в свой отладчик, чтобы точно узнать, где он падает, затем запускаете его снова и осторожно переходите к этому моменту, наблюдая за поведением вашего кода и состоянием любых соответствующих переменных.