Comments 12
Вывод: При использовании статических переменных в статических библиотеках нужно следить за тем, чтобы исполняемые модули не линковались статически друг в друга.Ещё лучше не использовать статических переменных. Они зло.
+5
Чтобы статья была как из песочницы, вначале лучше написать о том, что при сборке exe файла, доступ к статической переменной из методов класса будет происходить по двум разным адресам(для каждой статической линковки свой адрес), а итератор инициализируется адресом первой переменной и таким остается после вызова конструктора копирования. Для временных, экспериментальных нужд и итератор можно сделать static, чтобы первая схема линковки работала. Каждой паре по твари.
0
Для временных, экспериментальных нужд и итератор можно сделать static, чтобы первая схема линковки работала.
Но, согласитесь, в реальном коде Вы так специально делать не будете. А это пример из боевого кода, который привел к ошибке, которую я целый день ловил!
0
А тут как такого синглтона нет, получается другая концепция, т.е. одному объекту по смыслу соответствует несколько участков памяти
0
Посмотрел еще раз боевой код.
Здесь концепция такая: каждый объект класса является записью в некотором общем списке. Поэтому список статический, а итератор нет. Итератор является приватным членом класса. По сути этот класс представляет собой кэш. Там еще есть подсчет ссылок, поэтому две одинаковые записи списка не будут помещены в него дважды, плюс еще несколько дополнений, но я их убрал для упрощения.
Прошу прощения если я выбрал не самые понятные имена классов и методов. Хотел показать лишь саму ошибку.
Здесь концепция такая: каждый объект класса является записью в некотором общем списке. Поэтому список статический, а итератор нет. Итератор является приватным членом класса. По сути этот класс представляет собой кэш. Там еще есть подсчет ссылок, поэтому две одинаковые записи списка не будут помещены в него дважды, плюс еще несколько дополнений, но я их убрал для упрощения.
Прошу прощения если я выбрал не самые понятные имена классов и методов. Хотел показать лишь саму ошибку.
0
Забыл еще, дописать пункт 3: вызов копирующего конструктора происходит на стороне dll, можно проверить, взять адрес static списка в debug.
0
Напишите подробнее пожалуйста, а то непонятно в каком случае это происходит.
0
*3. .exe: Вызывается конструктор копирования для объекта класса ListAndIter. У временного объекта итератор стал не валидным. У нового объекта итератор указывает на список из DLL.dll, хотя сам объект создается на стороне exe-модуля.
Вот здесь на стороне dll, а не exe происходит вызов копируещего конструктора
0
> Как видно из кода, есть специальная функция foo, которая служит для обхода RVO, чтобы вызывался конструктор копирования.
Каким образом foo() убивает RVO? Или это только специфика MSVC? К сожалению сейчас нет доступа к windows-машине, а в том же gcc (можно попробовать например тут coliru.stacked-crooked.com/ ), никакого убивания RVO функцией foo нет :(
P.S. Вот такой код убивания вроде как более универсальный?
ListAndIter GetStaticObj( /* require evil */ bool condition = false )
{
if( condition ) {
ListAndIter obj;
return obj;
}
else {
ListAndIter obj;
return obj;
}
}
Каким образом foo() убивает RVO? Или это только специфика MSVC? К сожалению сейчас нет доступа к windows-машине, а в том же gcc (можно попробовать например тут coliru.stacked-crooked.com/ ), никакого убивания RVO функцией foo нет :(
P.S. Вот такой код убивания вроде как более универсальный?
ListAndIter GetStaticObj( /* require evil */ bool condition = false )
{
if( condition ) {
ListAndIter obj;
return obj;
}
else {
ListAndIter obj;
return obj;
}
}
0
Only those users with full accounts are able to leave comments. Log in, please.
Использование статических переменных и статическая линковка исполняемых модулей друг в друга