Ошибки, баги, вопросы - страница 3347

 
Vladimir Simakov #:
Вообще-то, адрес, по которому разыменовывать A::i  компилятору известен))) Ну, конечно, если это С++))). Требование инициализации статических полей класса происходит из того, что Declaration of a non-inline (since C++17) static data member inside a class definition не является definition. https://en.cppreference.com/w/cpp/language/definition На лицо, явный баг компилятора.

У нас тут MQL обсуждался, но раз пошел разговор за плюсы, то объясните мне, пожалуйста, откуда компилятору может быть известен адрес того, чего нет?


Вот простой кусок кода на C++.

class A
{
public:
        static int i;
};

A a;

int main()
{
        int i = a.i;
        return 0;
}


Из него генерится примерно такой ассемблерный код

main:
.....................
        movl    _ZN1A1iE(%rip), %eax
        movl    %eax, -4(%rbp)
.....................

У нас здесь есть только название чего-то 

_ZN1A1iE


И только компоновщик при попытке собрать исполняемый файл выдает ошибку.

/usr/bin/ld: /tmp/ccZMtngh.o: warning: relocation against `_ZN1A1iE' in read-only section `.text'
/usr/bin/ld: /tmp/ccZMtngh.o: in function `main':
a.cpp:(.text+0xa): undefined reference to `A::i'

Которую я понимаю как: упс, у меня здесь есть некий символ _ZN1A1iE и я не понимаю что подставить на его место


Если добавить определние статической переменной

class A
{
public:
        static int i;
};
int A::i = 777;

A a;

int main()
{
        int i = a.i;
        return 0;
}


То в ассемблере добавляется блок с описанием этой _ZN1A1iE

	.globl	_ZN1A1iE
	.data
	.align 4
	.type	_ZN1A1iE, @object
	.size	_ZN1A1iE, 4
_ZN1A1iE:
        .long   777

И все нормально собирается.

Если под "известный компилятору адрес" Вы имели ввиду это самое название на которое он может ссылаться, то ок. Иначе прошу объяснений :)

 
Ramil.Bagizov #:

Вот простой кусок кода на C++.

Из него генерится примерно такой ассемблерный код

А какое отношение этот код имеет к моему примеру?

У меня речь о том, что при прочих равных условиях в одном случае ошибка, а в другом ее нет
 
Ramil.Bagizov #:

Если объявляете статическую переменную, то следует ее и определить.

Попробуйте добавить в класс метод обращающийся к переменной и уже получите ошибку компиляции в коде класса


А принципиальная разница между вашими случаями (1) и (2) следующая (очень грубо):

Во втором случае вы объявляете глобальную переменную-экземпляр класса. Компилятору необходимо выделить память для нее и всего связанного с классом и здесь же компилятор пытается понять куда указывает имя `A::i`.

А в первом случае вы объявляете глобальную переменную-указатель на экземпляр класса. Здесь компилятору надо выделить память только для указателя, а сам объект будет создан уже в процессе выполнения программы.

И в первом и во втором случае создаётся объект класса A
 
Ramil.Bagizov #:

У нас тут MQL обсуждался, но раз пошел разговор за плюсы, то объясните мне, пожалуйста, откуда компилятору может быть известен адрес того, чего нет?


Вот простой кусок кода на C++.


Из него генерится примерно такой ассемблерный код

У нас здесь есть только название чего-то 


И только компоновщик при попытке собрать исполняемый файл выдает ошибку.

Которую я понимаю как: упс, у меня здесь есть некий символ _ZN1A1iE и я не понимаю что подставить на его место


Если добавить определние статической переменной


То в ассемблере добавляется блок с описанием этой _ZN1A1iE

И все нормально собирается.

Если под "известный компилятору адрес" Вы имели ввиду это самое название на которое он может ссылаться, то ок. Иначе прошу объяснений :)

Это не название чего-то, это имя метки. Вы не дочитали мой пост до конца или не поняли. Поясняю.

Есть Declaration, это когда мы объявили переменную. Компилятор абсолютно спокойно вводит имя метки и везде, где нужно делает rip адресацию через нее. Поэтому я и говорю, что компилятор ЗНАЕТ адрес переменной, потому, что эта метка должна появится потом и компоновщик вычислит смещение до нее и на выходе, естественно, не будет никаких меток, а будет вот это:


 
Vladimir Simakov #:

Поясняю.

Спасибо.
 

Такое ощущение, что не весь синтаксис SQLite поддерживается

input string str_Marka="ЗИЛ";//Марка
input string str_Model="КО";//Модель
...
string sql_query = 
    "SELECT " 
        "a.Id, " 
        "a.Title, " 
        "m.Value AS 'Марка', " 
        "mo.Value AS 'Модель', " 
        "y.Value AS 'Год выпуска', " 
        "(SELECT u_min.Time_db FROM Adv_update u_min WHERE u_min.Adv_Id = a.Id ORDER BY u_min.Time_db ASC LIMIT 1) AS 'Наименьшая дата', " 
        "(SELECT u_min.Price FROM Adv_update u_min WHERE u_min.Adv_Id = a.Id ORDER BY u_min.Time_db ASC LIMIT 1) AS 'Цена для наименьшей даты', " 
        "(SELECT u_max.Time_db FROM Adv_update u_max WHERE u_max.Adv_Id = a.Id ORDER BY u_max.Time_db DESC LIMIT 1) AS 'Наибольшая дата', " 
        "(SELECT u_max.Price FROM Adv_update u_max WHERE u_max.Adv_Id = a.Id ORDER BY u_max.Time_db DESC LIMIT 1) AS 'Цена для наибольшей даты' " 
    "FROM " 
        "Adv AS a " 
        "JOIN Adv_Prop AS m ON a.Id = m.Adv_Id AND LOWER(m.Name) = 'Марка' AND LOWER(m.Value) = LOWER('" + str_Marka + "') " 
        "JOIN Adv_Prop AS mo ON a.Id = mo.Adv_Id AND LOWER(mo.Name) = 'Модель' AND LOWER(mo.Value) LIKE LOWER('%" + str_Model + "%') "
        "JOIN Adv_Prop AS y ON a.Id = y.Adv_Id AND LOWER(y.Name) = 'Год выпуска' ";

Если я ввожу str_Marka="зил", то получаю пустой ответ - иначе говоря, оператор LOWER ничего не делает. При значении ЗИЛ - всё ищется - в базе записано "ЗИЛ"
Можете это проверить?

 
Aleksey Vyazmikin #:

Такое ощущение, что не весь синтаксис SQLite поддерживается

Если я ввожу str_Marka="зил", то получаю пустой ответ - иначе говоря, оператор LOWER ничего не делает. При значении ЗИЛ - всё ищется - в базе записано "ЗИЛ"
Можете это проверить?

Похоже на проблемы с локалью.

 
JRandomTrader #:

Похоже на проблемы с локалью.

Как то можно их решить?

 
Aleksey Vyazmikin #:

Как то можно их решить?

По идее, неплохо бы убедиться, что МТ и SQLite используют одну и ту же русскую локаль. Но не подскажу, как именно.

 

При запуске визуального тестирования окно тестера находится вот в таком положении:


И вот, после каждого запуска, чтобы добраться до полосы прокрутки логов, нужно или жать на кнопку, чтобы развернуть окно тестера, или сдвигать его мышкой.