2017-01-14 14 views
-1

У меня есть эта функция:Ошибки возвращение символа * в C++ функции

char* return_string(){ 
    char buffer[] = "Hi world!"; 
    return buffer; 
} 

bool test08() 
{ 
    char compare[] = "Hi world!"; 
    int result = strcmp(compare,return_string()); 
if (result == 0) return true; 
return false; 
} 
int main() 
{ 
if(test08) printf("\nTRUE"); 
else printf("\nFALSE"); 
} 

Почему этот код работать в c++ Shell, и он не в CodeBlocks v 13.12 (ошибка сегментации);. он будет работать, если я изменить свою char buffer[]= декларацию char *buffer=; я новичок в C++ (легко узнать), поэтому, пожалуйста, ясно ...

+1

Это неопределенное поведение. Вы возвращаете указатель на локальную переменную. –

+0

Не спам-теги несвязанных языков. – Olaf

ответ

1

Просто измените функцию return_string следующим образом

const char* return_string(){ 
    const char *buffer = "Hi world!"; 
    return buffer; 
} 

Проблема с оригинальной реализацией функции является то, что массив buffer является локальным массивом функции с автоматической продолжительностью хранения, которая не будет в живых после выхода из функция.

В модифицированной функции используется строковый литерал с длительностью статического хранения. Таким образом, вы можете вернуть указатель на первый символ строкового литерала.

Функция test08 можно записать проще

bool test08() 
{ 
    char compare[] = "Hi world!"; 
    return strcmp(compare, return_string()) == 0; 
} 
1

Это:

char* return_string(){ 
    char buffer[] = "Hi world!"; 
    return buffer; 
} 

копирует строку «Привет мир !» в локальную переменную buffer, а затем возвращает эту локальную переменную - это приводит к неопределенному поведению, если вы попытаетесь использовать это возвращаемое значение, потому что буфер отбрасывается при выходе функции.

Это:

char* return_string(){ 
     char *buffer = "Hi world!"; 
     return buffer; 
    } 

на самом деле было бы хорошо, хотя, вероятно, не то, что вы хотите. Вы бы возвращали адрес начала строкового литерала (хранящегося в таинственном месте, в стандарте), что нормально. В C++ у вас возникли бы проблемы с константой.

1

Ваша функция return_string возвращает указатель на локальную переменную buffer, которая определяется только в объеме return_string. Когда функция вернется, вы возвращаете адрес, где buffer используется для хранения, а значение, хранящееся в этом адресе, больше недействительно. Ну, если вы настаиваете на возвращении указатель на символ, вы можете динамически выделять «Hello World» и помню, чтобы освободить его позже:

char * return_string() { 
    char local_var[] = "hello world"; 
    char *buffer = (char *) malloc(sizeof(local_var)); 
    strcpy(buffer, local_var); // we know that buffer is big enough to hold local_var 
    return buffer; 
} 

Поскольку память, в которой «привет мир» хранится не локально к функции, он не будет освобожден при выходе из функции.

Другое (лучшее) решение - передать статически выделенный buffer (надеюсь, достаточно большой, чтобы сохранить ваше значение) до return_string и изменить его содержимое там.

void return_string(char *buffer, size_t buffer_size) { 
    strncpy(buffer, "hello world", buffer_size); 
} 
0

Вы возвращаете указатель на буфер, но переменная буфера уничтожается после возвращения функции.

Вам нужно сделать свою переменную буфера статической.

0

Это ответ на все, но все же ...
Я пробовал CodeBlocks 16.01 (mingw), и все работает плавно. Так что быстрое предложение, всегда старайтесь работать с обновленными версиями любого программного обеспечения, особенно если вы все еще участвуете в процессе обучения.

+0

Это типичный случай «неопределенного поведения» * случайно * работает, несмотря на то, что код неправильный, что затрудняет идентификацию ошибки. – merlinND

+0

C++ не работает таким образом. Просто потому, что он работает, это не значит, что код «хорошо». Возвращение адреса локальной переменной - это неопределенное поведение, независимо от того, что это за поведение. Он может работать, он может потерпеть неудачу, он может выйти из строя, если скомпилирован с различными параметрами, он может работать сегодня, не работает завтра и т. Д. – PaulMcKenzie