[noob; c++] ссылка на элемент массива

Yzzi

Есть такой кусок кода :

void run()
{
std::vector<std::string> v;
... // здесь v заполняется сторонней функцией
std::string & a = v[0];
std::string & b = v[1];
... // какой-то код, в котором a, b используются только для чтения, v не используется
}

run() вызывается в разных потоках.
Периодически программа падает (segmentation fault).
После замены замены ссылок на строки :

void run()
{
std::vector<std::string> v;
... // здесь v заполняется сторонней функцией
std::string a = v[0];
std::string b = v[1];
... // какой-то код, в котором a, b используются только для чтения, v не используется
}

программа падать перестала. Нагрузка - та же.
Собственно, вопрос : почему так происходит? Я понимаю, что ссылаться на элементы вектора - плохая затея, но там вроде реаллокаций нет (после определения ссылок), вектор вообще не трогается. Деструктор для a и b тоже вроде бы не должен вызываться.
Или это просто случайность и бага где-то в другом месте?

kokoc88

Или это просто случайность и бага где-то в другом месте?
Напиши const std::string&

istran

Если делать все так, как ты описал, ошибок быть не должно. Даже если бы ты менял a и b. Скорее всего ошибка в другом месте. Что дебагер говорит?

apl13

Чисто для интереса: платформа, компилятор, версия библиотеки?

apl13

Алсо да, ссылки, использующиеся только для чтения, обязаны быть константными.

Yzzi

ubuntu 10.04
gcc version 4.4.3

Maurog

Есть такой кусок кода
нужно больше кода. в приведенном коде проблем не видно. какой-то важный момент почикан руками :grin:

istran

Что имеется ввиду под "обязаны"?

agaaaa

Хм. А при чём здесь многопоточность, если в приведённом коде нет общих данных?

Serab

ну типа хороший тон. Ссылки вообще в таких ситуациях хз зачем нужны, если их не собираются модифицировать. А если собираются, то тоже похоже на говнокод, если честно. Но надо увидеть весь кусок, может там само изящество на самом деле.

margadon

ссылки зачем? ну либо указатели либо ссылки, не копировать же объекты. а так ссылка как алиас используется - удобно

margadon

вроде как std::string не thread-safe (по крайней мере в gcc) и даже при копировании (а вдруг под чтением подразумевалось копирование и чтение?) вполне может включить не-thread-safe-COW, который всё свалит

Maurog

может включить COW
это вырезали уже достаточно давно. больше таких сюрпризов в гцц нет

Serab

ссылки зачем? ну либо указатели либо ссылки, не копировать же объекты. а так ссылка как алиас используется - удобно
ну у меня нету предрассудков вроде «ни за что не копировать объект». Строки как-то привык копировать не парясь в основном. Не, если там все тормозит страшно из-за этого, то можно и подумать...

margadon

ну у меня нету предрассудков вроде «ни за что не копировать объект»
у меня нет предрассудков перед значком & и некоторыми очевидными оптимизациями
лишний раз копировать строку, если можно этого не делать, нужно делать осознанно

erotic

Напиши const std::string&
Как это защищает от v.clear()?

erotic

это вырезали уже достаточно давно. больше таких сюрпризов в гцц нет
Смотрел string в gcc-4.8.1, есть там упоминания COW с комментариями:

template<typename _CharT, typename _Traits, typename _Alloc>
class basic_string
....
// 3. _M_refcount has three states:
// -1: leaked, one reference, no ref-copies allowed, non-const.
// 0: one reference, non-const.
// n>0: n + 1 references, operations require a lock, const.

SEMEN73

Бабка Ванга подсказывает, что дело может быть в "оптимизации" вида "давайте удалим v, раз уж он дальше не используется"

Ivan8209

Это не так: объектно-ориентированные языки анти-модульные
и не допускают таких автоматических оптимизаций.
По крайней мере, такие, как C++.
---
"Унивеpситет pазвивает все способности, в том числе --- глупость."

apl13

ну у меня нету предрассудков вроде «ни за что не копировать объект». Строки как-то привык копировать не парясь в основном. Не, если там все тормозит страшно из-за этого, то можно и подумать...
О, а мне еще как-то попался cpp, внутри которого были определены функции, в одной из которых аргумент имел тип QString & (даже без const), а в другой std::string (безо всяких ссылок). Очень радовался.
При том что ни в одной из функций строковый аргумент, разумеется, не модифицировался.

Maurog

Смотрел string в gcc-4.8.1, есть там упоминания COW с комментариями:
действительно, комменты есть, только при беглом просмотре выяснил, что refcount может быть 0 или -1
и это не удивительно, так как COW противоречит стандарту C++11 (нарушает требования к сложности некоторых операций)
но само наличие атомарных операций удручает :(

Maurog

std::string не thread-safe (по крайней мере в gcc)
несмотря на COW std::string спокойно можно читать из нескольких потоков. есть простая гарантия многопоточности (как и у shared_ptr). это верно как для старых gcc, так и для новых

evgen5555

Собственно, вопрос : почему так происходит?
Посмотри стек в GDB в момент падения, все должно быть намного более очевидно, чем гадание по кускам странного кода.
Оставить комментарий
Имя или ник:
Комментарий: