Использование String c_str () для возврата char * - PullRequest
0 голосов
/ 08 июня 2018

Я работаю над устаревшим кодом, в котором я должен внести некоторые изменения в файл cpp. Файл cpp содержит весь код в extern блоке "c" -

Я обновил функцию, которая возвращает символ *Код выглядит примерно так как func1 () ниже.Поскольку я использую std :: strring и stringstream, я включил файлы заголовков sstream и string перед блоком extern.Следующая функция вызывается из файлов c и cpp. Так что я не могу вернуть std :: string здесь -

char* func1(someStruct* pt){
    std::strig nam = somefunc(pt);
    //have to append some integer in particular format
    std::stringstream ss;
    ss<<nam<<pt->int1 ......;

    nam = ss.str(); 
    //More code here for returning char* based on queries - (a)
}

В одном из мест, где эта функция вызывается -

void otherFunc(.....){
    //......
    char* x = func(myptr);
    if(based_on_some_condition){
        char* temp = func3(x); //returns a char* to dynamically allocated array.
        strcpy(x,temp);       //copying (b)

    }
    //..........
}

Ниже приведен мой запрос -
1) В (a) я могу вернуть char * в следующих 2 формах. Я должен принять решение, чтобы копирование в (b) не вызывало неопределенного поведения -

i)Create a char array dynamically with size = nam.length()+10 (extra 10 for some work happening in func3).<br>
    char* rtvalue = (char*)calloc(sizeof(char),nam.length()+10);
    strcpy(rtvalue,nam.c_str());
    return rtvalue;
    And free(temp); in otherFunc() after strcpy(x,temp);

ii) Declare 'nam' as static std::string nam;
    and simply return const_cast<char*>(nam.c_str());
    Will defining 'nam' with static scope ensure that a correct return happen from function (ie no dangling pointer at 'x')?
    More importantly, can I do this without worrying about modification happening at (b).

Какое решение лучше?

Ответы [ 2 ]

0 голосов
/ 08 июня 2018

Это правда, что вы должны вернуть string, но если вам абсолютно необходимо вернуть char*, первый метод лучше.И не забудьте free.В противном случае выражения типа strcmp(f(pt1), f(pt2)) будут возвращать непредсказуемые результаты.

0 голосов
/ 08 июня 2018

Проблема возвращается char *.Когда вы используете C ++, вы не должны использовать этот тип.Это не С!std::string или std::vector<char> следует использовать.

Если вы будете использовать char * в качестве типа возврата в этом типе функции, это приведет к неопределенному поведению (доступ к освобожденной памяти) или утечке памяти.

Если вы будете использовать static std::string nam;, функция будет поддерживать внутреннее состояние, и это всегда приводит к проблемам.Например, если вы создадите функциональность потоков, у вас будет неопределенное поведение.Еще хуже, если вы по какой-то причине будете использовать эту функцию дважды, результат второго вызова будет влиять на результат для первого вызова (например, ваш коллега будет использовать эту функцию, поскольку он не будет ожидать скрытых побочных эффектов).

ЕслиВы разрабатываете некоторый API, который должен быть доступен из кода C, чем вы должны разрабатывать этот API другим способом.Я не знаю, какую функциональность вы предоставляете, скорее всего, вам нужно что-то вроде этого:

char *func1(someStruct* pt, char *result, int size){ // good name could be like this: appendStructDescription
    std::strig nam = somefunc(pt);
    //have to append some integer in particular format
    std::stringstream ss;
    ss<<nam<<pt->int1 ......;

    nam = ss.str(); 

    int resultSize = std::min(size - 1, nam.length());
    memcpy(result, nam.c_str(), resultSize);
    result[resultSize] = 0;
    return result + resultSize;
}

Этот подход имеет большие преимущества: ответственность за управление памятью переходит к вызывающей стороне, пользователь API понимает, чтоожидается.

...