2010-11-19 2 views
4

Допустим, что функция, которая возвращает фиксированный «случайный текст» строка записывается какC/C++ Char Указатель Краш

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

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

Function1()[1]=’a’; 

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

+1

[1] указывает на 2-й символ в строке ([0] будет первым) – climbage

+0

Почему вы говорите C++ в названии, но отметьте вопрос C? – GManNickG

+1

Вы должны пометить это как MSVC, так как gcc (по крайней мере> = 4) предупредит вас о назначении char const [] символу * устаревшим ... по уважительным причинам, как вы видите. – mmmmmmmm

ответ

12

Строка, возвращаемая функцией, обычно хранится в части только для чтения вашего процесса. Попытка изменить его приведет к нарушению доступа. (EDIT: Строго говоря, это неопределенное поведение, и в некоторых системах это приведет к нарушению доступа. Спасибо, Джон).

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

+4

Вы не можете сказать, что это приведет к нарушению доступа. C++ ничего не знает о нарушениях доступа. Все, что вы действительно можете сказать, это то, что он вызовет неопределенное поведение. –

+1

@ Джон: вы правы. Возьмите это в философском смысле тогда :) –

+0

@John: Может быть, «будет» слишком строчно, но у вас есть хороший шанс, что он будет :-) – mmmmmmmm

0

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

1

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

+0

Конечно, вы можете * использовать * его. Вы просто не можете изменять его содержимое. –

+0

ohya, точно. и еще одна вещь (точно так же, как работы ... :), как многие другие ребята уже сказали, преобразование константной строки char в непостоянную строку char - это бла-бла-бла ... вы знаете ~ –

4

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

+0

Полностью согласен. –

+1

это должно быть 'std :: string', поскольку OP хочет изменить значение, возвращаемое из функции –

+0

Да, Джон, на C++ - уверен, на C - это единственный способ. –

3

Вы пытаетесь изменить строковый литерал. Согласно Стандарту это вызывает undefined behavior. Еще одна вещь, которую следует иметь в виду (связанная), состоит в том, что строковые литералы всегда имеют тип const char*. Существует специальная диспенсация для преобразования указателя в строковый литерал в char*, забрав квалификатор const, но основная строка - still 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'; 
} 
0

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

char Function1Str[] = "Some text"; 

char *Function1() 
{ 
    return Function1Str; 
} 
0

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

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

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) было бы хорошей практикой, но вы можете быть довольно крутой кривой обучения для вас.