2016-07-04 2 views
0
#include<stdio.h> 
#include<string.h> 
#include<stdlib.h> 

char *func(char * str){ 


    int len; 
    len=strlen(str)+3; 
    str = (char *)realloc(str,len); 
    return str; 


} 

void main(){ 

    printf("str:%s",func("hello")); 

} 

Окончательные отпечатки ans (null), вместо печати строки: «привет». Может кто-нибудь объяснить, почему это так? Я не могу идентифицировать ошибку. Может ли кто-нибудь исправить ошибку и помочь мне с рабочим кодом. Пожалуйста!Почему realloc не работает должным образом в этом случае?

+1

'void main() {..' Не удивительно .... –

+3

Вы вызываете realloc на char *, который не может быть перераспределен. Таким образом, он терпит неудачу и возвращает NULL. –

+0

Вопрос помечен как «динамическое распределение», и все же нет никого в виду ... @WilliamPursell. Не следует ли это генерировать предупреждение или полный сбой компиляции для передачи «char const *» (тип строкового литерала) to 'func()'? Я в основном программирую C++ 14 со всеми предупреждениями, поэтому, возможно, я слишком привык к безопасности хорошего типа ... –

ответ

6

Ваша программа вызывает undefined behavior, потому что вы передаете указатель, который ранее не возвращался семейством функций распределения памяти динамических памяти, до realloc().

Согласно C11, глава §7.22.3.5, перераспределить функции (курсив мой)

Если ptr пустой указатель, функция realloc ведет себя как malloc функции для указанный размер. В противном случае, если ptr не совпадает с указателем ранее возвращенным функцией управления памятью , или если пространство было высвобождено с помощью вызова функции free или realloc, поведения не определенно. [...]

Это говорит,

+1

@ Анонимный [предпочитаемый способ в stackoverflow сказать "спасибо"] (http://meta.stackexchange.com/a/5235/202811) –

1

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

Что вы можете сделать, это следующее

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

char *func(const char * str) 
{ 
    size_t len = strlen(str) + 3; 

    char *tmp = realloc(NULL, len); 

    if (tmp) strcpy(tmp, str); 

    return tmp; 
} 

int main(void) 
{ 
    char *str = func("hello"); 

    if (str) printf("str: %s\n", str); 

    free(str); 
} 

Выход программы

str: hello 

Примите во внимание, что вызов

realloc(NULL, len) 

эквивалентно

malloc(len) 
+0

' realloc (NULL, len); 'Почему не просто' malloc (len) '? Они эквивалентны, но последние кажутся лучше семантически. –

+0

@underscore_d Потому что вопрос о realloc. –

6

"hello" является только для чтения строки буквального. Его тип действительно const char*, хотя компиляторы позволяют назначать char*, несмотря на все веселье, которое это вызывает.

Поведение при вызове realloc на такой указатель undefined. Поэтому компилятор может делать все, что ему нравится. Это может съесть вашу кошку.