Строки - обращение на прямую
От: dosik Россия www.dosik.ru
Дата: 30.08.15 06:19
Оценка:
Интересно, на сколько допустимо лезть на прямую в память строк, например:
    std::string mfn(MAX_PATH, 0);
    DWORD size = GetModuleFileName(NULL, &mfn[0], mfn.size());

По уму в строках память должна выделяться непрерывно, но вот может ли это измениться?
Re: Строки - обращение на прямую
От: _Butch_  
Дата: 30.08.15 06:29
Оценка: -1 :)
Здравствуйте, dosik, Вы писали:

D>Интересно, на сколько допустимо лезть на прямую в память строк, например:

D>
D>    std::string mfn(MAX_PATH, 0);
D>    DWORD size = GetModuleFileName(NULL, &mfn[0], mfn.size());
D>


Ни насколько не допустимо. К тому же, mfn.size() в данном случае 0.


D>По уму в строках память должна выделяться непрерывно, но вот может ли это измениться?


Это тебе кажется, что "по уму", а мне кажется, что есть стандарт языка, и в нём непрерывность гарантируется только для std::vector (и для std::string::c_str(), но этот метод возвращает константный указатель, который теоретически не обязан совпадать с собственно внутренним буфером строки).
Re: Строки - обращение на прямую
От: VTT http://vtt.to
Дата: 30.08.15 07:14
Оценка:
Здравствуйте, dosik, Вы писали:

D>Интересно, на сколько допустимо лезть на прямую в память строк, например:

D>
D>    std::string mfn(MAX_PATH, 0);
D>    DWORD size = GetModuleFileName(NULL, &mfn[0], mfn.size());
D>

D>По уму в строках память должна выделяться непрерывно, но вот может ли это измениться?

Дело в том, что непрерывность массива символов гарантирована только для указателей, возвращаемых при вызове data() и c_str(), но при этом сами массивы доступны только для чтения. Это вроде как было сделано в древние времена чтобы позволить использовать в реализациях ::std::string всякие хитрые приемы (типа copy on write) для снижения количества копирования. Запись минуя методы string посредством хаков вроде const_cast<char *>(text.data()) или &text[0] — это прямой путь в область неопределенного поведения и удивительных багов. Так что не делайте так. Выделяйте буффер (или просто массив на стеке) и копируйте через него. И используйте GetModuleFileNameW.
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Re[2]: Строки - обращение на прямую
От: Stanislav V. Zudin Россия  
Дата: 30.08.15 07:34
Оценка: +2
Здравствуйте, _Butch_, Вы писали:

_B_>Здравствуйте, dosik, Вы писали:


D>>Интересно, на сколько допустимо лезть на прямую в память строк, например:

D>>
D>>    std::string mfn(MAX_PATH, 0);
D>>    DWORD size = GetModuleFileName(NULL, &mfn[0], mfn.size());
D>>


_B_>Ни насколько не допустимо. К тому же, mfn.size() в данном случае 0.


не 0, а MAX_PATH (см. к-тор).

D>>По уму в строках память должна выделяться непрерывно, но вот может ли это измениться?


_B_>Это тебе кажется, что "по уму", а мне кажется, что есть стандарт языка, и в нём непрерывность гарантируется только для std::vector (и для std::string::c_str(), но этот метод возвращает константный указатель, который теоретически не обязан совпадать с собственно внутренним буфером строки).


В '03 не не обязана выделяться непрерывно, а в '11 должна.
_____________________
С уважением,
Stanislav V. Zudin
Re[2]: Строки - обращение на прямую
От: Vlad_SP  
Дата: 30.08.15 07:45
Оценка:
Здравствуйте, VTT,

VTT>Дело в том, что непрерывность массива символов гарантирована только для указателей, возвращаемых при вызове data() и c_str(), но при этом сами массивы доступны только для чтения.


Начиная с C++11 непрерывность массива символов гарантируется (21.4.1/5).

VTT>И используйте GetModuleFileNameW.


С какой это стати??
Re[3]: Строки - обращение на прямую
От: VTT http://vtt.to
Дата: 30.08.15 08:15
Оценка: +1
Здравствуйте, Vlad_SP, Вы писали:

V_S>Начиная с C++11 непрерывность массива символов гарантируется (21.4.1/5).

Начиная с C++11 c его move семантикой и умными указателями фокусы с copy on write и совместным владением буфферами по идее больше не нужны, так что они могли бы сделать и не const data() и давать писать в буфер строки напрямую.

V_S>С какой это стати??

т.е. как с какой? не каждый путь в ANSI строчке может быть представлен
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Re[4]: Строки - обращение на прямую
От: Vlad_SP  
Дата: 30.08.15 08:46
Оценка:
Здравствуйте, VTT, Вы писали:

VTT>т.е. как с какой? не каждый путь в ANSI строчке может быть представлен


Да-да-да. И будем уникодные символы запихивать в std::string?
Re[5]: Строки - обращение на прямую
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 30.08.15 09:46
Оценка:
Здравствуйте, Vlad_SP, Вы писали:

V_S>Да-да-да. И будем уникодные символы запихивать в std::string?


После перевода в UTF-8.
Ce n'est que pour vous dire ce que je vous dis.
Re[3]: Строки - обращение на прямую
От: dosik Россия www.dosik.ru
Дата: 30.08.15 10:55
Оценка:
Здравствуйте, Vlad_SP, Вы писали:

V_S>Начиная с C++11 непрерывность массива символов гарантируется (21.4.1/5).


Ну в общем то как думалось мне. По ленился сам в стандарте посмотреть.
В любом случае сделал через буфер. Просто было интересно.

Спасибо.
Re[6]: Строки - обращение на прямую
От: -MyXa- Россия  
Дата: 30.08.15 11:14
Оценка: 5 (1)
Здравствуйте, Don Reba, Вы писали:

DR>После перевода в UTF-8.


Подкреплю твои слова вот этой ссылкой.
Если не поможет, будем действовать током... 600 Вольт (C)
Re[4]: Строки - обращение на прямую
От: Vamp Россия  
Дата: 30.08.15 13:23
Оценка:
D>В любом случае сделал через буфер. Просто было интересно.
В результате имеем лишнее копирование. В С++11 я бы копировал напрямую в string.
Да здравствует мыло душистое и веревка пушистая.
Re[5]: Строки - обращение на прямую
От: dosik Россия www.dosik.ru
Дата: 30.08.15 13:47
Оценка:
Здравствуйте, Vamp, Вы писали:

V>В результате имеем лишнее копирование. В С++11 я бы копировал напрямую в string.


Согласен. Но тут еще одна подоплека: разумеется потом выполняем resize() по фактическому размеру строки, а потом желательно бы и shrink_to_fit(), чтобы не таскать с собой излишний буфер. И вот как будет себя вести shrink_to_fit() прямо не известно. Да и как-то кажется мне это дурным тоном, хотя...
Re[6]: Строки - обращение на прямую
От: VTT http://vtt.to
Дата: 30.08.15 16:21
Оценка:
Здравствуйте, dosik, Вы писали:

D>Согласен. Но тут еще одна подоплека: разумеется потом выполняем resize() по фактическому размеру строки, а потом желательно бы и shrink_to_fit(), чтобы не таскать с собой излишний буфер. И вот как будет себя вести shrink_to_fit() прямо не известно. Да и как-то кажется мне это дурным тоном, хотя...


Можно сначала узнать требуемый размер строки от GetModuleFileName и выделить память сразу под него.
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Re[7]: Строки - обращение на прямую
От: dosik Россия www.dosik.ru
Дата: 30.08.15 20:47
Оценка:
Здравствуйте, VTT, Вы писали:

VTT>Можно сначала узнать требуемый размер строки от GetModuleFileName и выделить память сразу под него.


Да вот в том то и дело, что не умеет он говорить сколько нужно... Он возвращает только столько, сколько влезло в буфер, а если буфера не хватило, то в GetLastError помещает ERROR_INSUFFICIENT_BUFFER.
Re[5]: Строки - обращение на прямую
От: Warturtle  
Дата: 31.08.15 06:29
Оценка:
Здравствуйте, Vlad_SP, Вы писали:

V_S>Здравствуйте, VTT, Вы писали:


VTT>>т.е. как с какой? не каждый путь в ANSI строчке может быть представлен


V_S>Да-да-да. И будем уникодные символы запихивать в std::string?

std::string — это std::basic_string< char >, но существует и std::basic_string< wchar_t >.
Re[6]: Строки - обращение на прямую
От: Vlad_SP  
Дата: 31.08.15 06:49
Оценка:
Здравствуйте, Warturtle,

W>std::string — это std::basic_string< char >, но существует и std::basic_string< wchar_t >.


Спасибо, я в курсе Но ТС задал вопрос именно о std::basic_string< char >.
Re[6]: Строки - обращение на прямую
От: Vlad_SP  
Дата: 31.08.15 06:51
Оценка:
Здравствуйте, Don Reba,

гм, разве в исходном сообщении ТС было что-нибудь сказано о "переводе"?
Re[7]: Строки - обращение на прямую
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 31.08.15 07:10
Оценка:
Здравствуйте, Vlad_SP, Вы писали:

V_S>гм, разве в исходном сообщении ТС было что-нибудь сказано о "переводе"?


Разговор об использовании API в любом случае имеет косвенное отношение к исходному сообщению.
Ce n'est que pour vous dire ce que je vous dis.
Re: Строки - обращение на прямую
От: dosik Россия www.dosik.ru
Дата: 08.09.15 17:26
Оценка:
В продолжении разговора, вот вторая реанкорнация с вкусностями С++11.
Посмотрите, нет ли тут утечки памяти:
    size_t size = MAX_PATH;
    std::unique_ptr<char[]> buff(new char[size]);
    DWORD mfn_size = GetModuleFileName(NULL, &buff[0], size);
    while (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
    {
        size *= 2;
        buff = std::unique_ptr<char[]>(new char[size]);        //Происходит ли удаление старого буфера тут?
        mfn_size = GetModuleFileName(NULL, &buff[0], size);
    }

    string path(std::move(&buff[0]));                //Действительно ли это будет оптимальней, нежели string path(&buff[0])
Re[2]: Строки - обращение на прямую
От: watchmaker  
Дата: 08.09.15 18:07
Оценка:
Здравствуйте, dosik, Вы писали:

D>        buff = std::unique_ptr<char[]>(new char[size]);        //Происходит ли удаление старого буфера тут?

Да.

D>    string path(std::move(&buff[0]));                //Действительно ли это будет оптимальней, нежели string path(&buff[0])

Оптимальней не будет, лучше выбрать вариант без std::move.
У фундаментальных типов (у указателя в данном случае) вообще нет перемещающих конструкторов — всё делается через копирование. Ну и смысла в существовании перегрузки конструктора string, принимающего r-value ссылку на указатель, тоже нет никакого по этим причинам. Так что стоит предпочесть более короткий и понятный код.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.