C / C ++ Char Pointer Crash - PullRequest
       2

C / C ++ Char Pointer Crash

4 голосов
/ 19 ноября 2010

Допустим, что функция, которая возвращает фиксированную строку 'произвольный текст', записывается как

char *Function1()
{ 
return “Some text”;
}

, тогда программа может аварийно завершить работу, если она случайно попытается изменить значение, выполнив

Function1()[1]=’a’;

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

Ответы [ 7 ]

12 голосов
/ 19 ноября 2010

Строка, которую вы возвращаете в функцию, обычно хранится в доступной только для чтения части вашего процесса. Попытка изменить его приведет к нарушению прав доступа. (РЕДАКТИРОВАТЬ: Строго говоря, это неопределенное поведение, и в некоторых системах это приведет к нарушению доступа. Спасибо, Джон).

Обычно это происходит потому, что сама строка жестко запрограммирована вместе с кодом вашего приложения. При загрузке устанавливаются указатели, указывающие на те разделы вашего процесса, доступные только для чтения, которые содержат буквенные строки. Фактически, всякий раз, когда вы пишете какую-то строку в C, она обрабатывается как const char* (указатель на постоянную память).

4 голосов
/ 19 ноября 2010

Подпись этой функции действительно должна быть constchar* Function();.

3 голосов
/ 19 ноября 2010

Вы пытаетесь изменить строковый литерал. Согласно Стандарту, это вызывает неопределенное поведение . Еще одна вещь, которую нужно иметь в виду (связанная), это то, что строковые литералы всегда имеют тип const char*. Существует специальное разрешение для преобразования указателя на строковый литерал в char*, убирая квалификатор const, но базовая строка все еще равна . Таким образом, делая то, что вы делаете, вы пытаетесь изменить const. Это также вызывает неопределенное поведение и похоже на попытку сделать это:

const char* val = "hello";
char* modifyable_val = const_cast<char*>(val);
modifyable_val[1] = 'n';  // this evokes UB

Вместо того, чтобы возвращать const char* из вашей функции, возвращайте string по значению. Это создаст новый string на основе строкового литерала, и вызывающий код может делать все, что захочет:

#include <string>

std::string Function1()
{ 
return “Some text”;
}

... позже:

std::string s = Function1();
s[1] = 'a';

Теперь, если вы пытаетесь изменить значение, которое Function() возвращается, вам придется сделать что-то еще. Я бы использовал класс:

#include <string>
class MyGizmo
{
public: 
  std::string str_;
  MyGizmo() : str_("Some text") {};
};

int main()
{
  MyGizmo gizmo;
  gizmo.str_[1] = 'n';
}
1 голос
/ 19 ноября 2010

Вы можете использовать статическую строку символов для возвращаемого значения, но вы никогда не используете ее.Это как ошибка нарушения прав доступа.Поведение этого не определено в c ++ Standard.

0 голосов
/ 19 ноября 2010

Вопрос показывает, что вы не понимаете строковые литералы.

изображение этого кода

char* pch = "Here is some text";
char* pch2 = "some text";
char* pch3 = "Here is";

Теперь, как компилятор выделяет память для строк, полностью зависит от компилятора. память может быть организована так:

Here is<NULL>Here is some text<NULL>

с pch2, указывающим на область памяти внутри строки pch.

Ключ здесь - понимание памяти. Использование стандартной библиотеки шаблонов (stl) было бы хорошей практикой, но вы можете быть довольно крутой кривой обучения для вас.

0 голосов
/ 19 ноября 2010

Обратите внимание, что вы можете избежать сбоя, поместив текст в обычный массив:

char Function1Str[] = "Some text";

char *Function1()
{
    return Function1Str;
}
0 голосов
/ 19 ноября 2010

Это не скобки, а назначение. Ваша функция возвращает не простой символ *, а постоянный символ * (здесь я могу ошибаться, но память доступна только для чтения), поэтому вы пытаетесь изменить неизменяемую память. И скобки - они просто дают вам доступ к элементу массива.

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