2014-02-17 3 views
1

Когда я запускаю следующий исходный код, получил «ошибки сегментации (ядро сбрасывали)» на линии № 3станд :: сверять :: преобразования, вызванные ошибки сегментации

char s[] = "helloworld"; 
const std::collate<char>* pc = &std::use_facet<std::collate<char> >(std::locale("en_US")); 
std::string str = pc->transform(s, s + std::strlen(s)); 
std::cout << str.length() << "," << str << std::endl; 

Если я заменить строку # 2 с

const std::collate<char>* pc = new std::collate_byname<char>("en_US"); 

Я могу получить правильный результат. Я думаю, что результат этих двух строк должен быть таким же, все они получают результат из среды исполнения, так почему первый получил ошибку? Я сделал что-то не так?

PS: Компилятор C++ g ++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-3).

ответ

4

Чтение docs of use_facet:

Ссылка возвращаемый этой функцией является действительным до тех пор, пока существует какой-либо std::locale объект, который реализует Facet.

Вы создаете в своем коде временного std::locale, так что временно разрушаются в конце выражения, и вы остаются с оборванным указателем. Как это, он должен работать:

char s[] = "helloworld"; 
std::locale en_US("en_US"); 
const std::collate<char>* pc = &std::use_facet<std::collate<char> >(en_US); 
std::string str = pc->transform(s, s + std::strlen(s)); 
std::cout << str.length() << "," << str << std::endl; 
+0

Спасибо, это работает. – songyuanyao

+1

Я ошибочно считал, что 'std :: locale (" en_US ")' будет глобальным объектом, но только 'std :: locale()' и 'std :: locale :: classic()' глобальны на самом деле , – songyuanyao

+1

@songyuanyao Чтобы выразить это точно: объект 'std :: locale' - это просто немой (ish) набор указателей на грани, причем сами грани являются ссылочными. 'classic()' возвращает фактическую ссылку C++ для глобального экземпляра C-locale, в то время как пустой 'std :: locale' ctor возвращает копию глобальной локали (увеличивая количество ссылок на ее грани). Построение другого языкового стандарта даст вам объект локали, грани которого (потенциально) используются только этим объектом - ref. count 1. Потеряйте этот объект и грани вниз до 0 и уничтожайте. – Angew