Вопрос по c++, string – запись непосредственно во внутренние буферы std :: string

32

Я искал способ вставить некоторые данные в строку через границу DLL. Поскольку мы используем разные компиляторы, все наши dll-интерфейсы являются простыми символами *.

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

<code>string stringToFillIn(100, '\0');
FunctionInDLL( stringToFillIn.c_str(), stringToFillIn.size() );   // definitely WRONG!
FunctionInDLL( const_cast<char*>(stringToFillIn.data()), stringToFillIn.size() );    // WRONG?
FunctionInDLL( &stringToFillIn[0], stringToFillIn.size() );       // WRONG?
stringToFillIn.resize( strlen( stringToFillIn.c_str() ) );
</code>

Наиболее перспективным выглядит & amp; stringToFillIn [0], но является ли это правильным способом сделать это, учитывая, что вы думаете, что string :: data () == & amp; string [0]? Это кажется противоречивым.

Или лучше проглотить дополнительное выделение и избежать вопроса:

<code>vector<char> vectorToFillIn(100);
FunctionInDLL( &vectorToFillIn[0], vectorToFillIn.size() );
string dllGaveUs( &vectorToFillIn[0] );
</code>

Ваш Ответ

8   ответов
3

пока C ++ 11 дает непрерывные гарантии памяти, в производственной практике это «хаки». Метод очень популярен:

std::string stringToFillIn(100, 0);
FunctionInDLL(stringToFillIn.data(), stringToFillIn.size());
Error: User Rate Limit Exceededen.cppreference.com/w/cpp/string/basic_string/dataError: User Rate Limit Exceeded
23

std::string хранится какchar*, Самый портативный способ, который я могу придумать, это использоватьstd::vector, который гарантированно хранит свои данные в непрерывной порции памяти:

std::vector<char> buffer(100);
FunctionInDLL(&buffer[0], buffer.size());
std::string stringToFillIn(&buffer[0]);

Это, конечно, потребует двойного копирования данных, что немного неэффективно.

Error: User Rate Limit Exceededstd::stringError: User Rate Limit Exceededchar*Error: User Rate Limit Exceededstd::stringError: User Rate Limit Exceededchar. en.cppreference.com/w/cpp/string/basic_string
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededstackoverflow.com/questions/11149665/….
0

: string - это API, а некоторые - поведение, а не структура памяти реализации.

Поэтому, если вы используете разные компиляторы, вы не можете предполагать, что они одинаковы, поэтому вам нужно будет переносить фактические данные. Как уже говорили другие, перенесите символы и вставьте новую строку std :: string.

3

: string и не отправляю указатель на внутренние буферы через границы dll. Вместо этого я бы использовал простой буфер символов (статически или динамически размещаемый). После возврата вызова dll я позволю std :: string получить результат. Просто интуитивно кажется неправильным позволять вызываемым абонентам писать во внутренний буфер классов.

0

но будет смежной), поэтому я просто упомяну точку распределения / освобождения. В прошлом у меня были проблемы, когда я выделял память в dll (т. Е. Dll возвращала строку), которые вызывали ошибки при уничтожении (вне dll). Чтобы исправить это, вы должны убедиться, что ваш распределитель и пул памяти согласованы через границу DLL. Это сэкономит вам время на отладку;)

20

: c_str и string :: data могут законно возвращать указатель на буфер, который не имеет ничего общего с тем, как хранится сама строка. Возможно, что строка хранится, например, в сегментах. Запись в эти буферы оказывает неопределенное влияние на содержимое строки.

Кроме того, string :: operator [] не должен использоваться для получения указателя на последовательность символов - он должен использоваться только для одиночных символов. Это связано с тем, что эквивалентность указателя / массива не сохраняется в строке.

Что очень опасно в этом, так это то, что он может работать на некоторых реализациях, но затем внезапно обрывается без видимой причины в будущем.

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

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded markh44
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededherbsutter.wordpress.com/2008/04/07/…Error: User Rate Limit Exceeded
9

string::c_str() а такжеstring::data(), Кроме того, как объясняется в других ответах, вы не должны использоватьstring::operator[] чтобы получить указатель на последовательность символов - его следует использовать только для отдельных символов.

Начиная с C ++ 11 строки используют непрерывную память, так что вы можете использовать&string[0] получить доступ к внутреннему буферу.

2

я бы сказал, что это нормально и удобно / эффективно напрямую записывать в std :: string. я хотел бы использовать&s.front() чтобы получитьchar *, как в этом примере mex:

#include "mex.h"
#include <string>
void mexFunction(
    int nlhs,
    mxArray *plhs[],
    int nrhs,
    const mxArray *prhs[]
)
{
    std::string ret;
    int len = (int)mxGetN(prhs[0]);
    ret.reserve(len+1);
    mxGetString(prhs[0],&ret.front(),len+1);
    mexPrintf(ret.c_str());
}
string.front()Error: User Rate Limit Exceeded&string[0]Error: User Rate Limit Exceeded

Похожие вопросы