Помогите, пожалуйста, найти ошибку в коде
От: DSblizzard Россия  
Дата: 08.11.07 03:22
Оценка:
template <class T>
void sozd(T* Mas_1x, int Razm) {
    Mas_1x = new T [Razm];
}

template <class TElem, class TZnach>
void prisv(TElem* Mas, int Nom, TZnach Znach) {
    Mas[Nom] = (TElem) Znach;
}

template <class T>
void prisv(T* Mas, int KolArg, T Arg1, T ...) {
    Mas[0] = Arg1;
    va_list Args;
    va_start(Args, Arg1);
    for (int i = 1; i < KolArg; i++) {
        prisv<T, T>( Mas, i, va_arg(Args, T) ); // При 2-м проходе (иногда позже) ошибка. Почему?
    }
    va_end(Args);
}

int RazmMasOboznOper = 17;
string* MasOboznOper;
void inic_mas_obozn_oper() {
    sozd(MasOboznOper, RazmMasOboznOper);
    prisv<string>(MasOboznOper, RazmMasOboznOper, "=", "<", "<=", "==", 
            ">=", ">", "!=", "+", "-", "*", "/", "^", "!", 
            "&", "|", "=>", "<=>");
}

void main() {
  inic_mas_obozn_oper();
}

Добавлена разметка — Кодт
Программировать сложно. Но не программировать еще сложнее.
Re: Помогите, пожалуйста, найти ошибку в коде
От: LaptevVV Россия  
Дата: 08.11.07 06:26
Оценка:
Здравствуйте, DSblizzard, Вы писали:

DS>template <class T>

DS>void sozd(T* Mas_1x, int Razm) {
DS> Mas_1x = new T [Razm];
DS>}
А ты не забыл, что указатель передается по значению? Здесь нужно возвращать указатель, а не void.

DS>void main() {

DS> inic_mas_obozn_oper();
DS>}
Сделай int main()
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: Помогите, пожалуйста, найти ошибку в коде
От: DSblizzard Россия  
Дата: 08.11.07 07:05
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>А ты не забыл, что указатель передается по значению? Здесь нужно возвращать указатель, а не void.


Так лучше?
void sozd(T*& Mas_1x, int Razm)

LVV>Сделай int main()

Так и думал, что кто-нибудь на это укажет . Нет, дело не в этом. Проверьте в компиляторе — ни то, ни другое не решает проблему.
Программировать сложно. Но не программировать еще сложнее.
Re[3]: Помогите, пожалуйста, найти ошибку в коде
От: Nose Россия  
Дата: 08.11.07 07:41
Оценка: :)
Здравствуйте, DSblizzard, Вы писали:

DS>Так и думал, что кто-нибудь на это укажет . Нет, дело не в этом. Проверьте в компиляторе — ни то, ни другое не решает проблему.


Страшно компилятору такое скармливать. Обидится компилятор, и не будет мне больше компилировать.
... << RSDN@Home 1.2.0 alpha rev. 782>>
Re[3]: Помогите, пожалуйста, найти ошибку в коде
От: LaptevVV Россия  
Дата: 08.11.07 09:31
Оценка:
Здравствуйте, DSblizzard, Вы писали:

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


LVV>>А ты не забыл, что указатель передается по значению? Здесь нужно возвращать указатель, а не void.


DS>Так лучше?

DS>void sozd(T*& Mas_1x, int Razm)
Я б сделал непосредственно возврат указателя:
T * sozd(int Razm)
{ return new T[Razm]; }


LVV>>Сделай int main()

DS>Так и думал, что кто-нибудь на это укажет . Нет, дело не в этом. Проверьте в компиляторе — ни то, ни другое не решает проблему.
Понятно, что к проблеме не относится... Но лучше сразу приучаться следовать стандарту... Иначе в один прекрасный день...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Помогите, пожалуйста, найти ошибку в коде
От: Alexey Borodin alexey-borodin@narod.ru
Дата: 08.11.07 09:44
Оценка:
Здравствуйте, DSblizzard, Вы писали:

Плохо отформатирован.
Re: Помогите, пожалуйста, найти ошибку в коде
От: e-garin Россия  
Дата: 08.11.07 10:11
Оценка: 2 (1)
Здравствуйте, DSblizzard, Вы писали:
DS>template <class T>
DS>void sozd(T* Mas_1x, int Razm) {
DS>    Mas_1x = new T [Razm];
DS>}

DS>template <class TElem, class TZnach>
DS>void prisv(TElem* Mas, int Nom, TZnach Znach) {
DS>    Mas[Nom] = (TElem) Znach;
DS>}

DS>template <class T>
DS>void prisv(T* Mas, int KolArg, T Arg1, T ...) {
DS>    Mas[0] = Arg1;
DS>    va_list Args;
DS>    va_start(Args, Arg1);
DS>    for (int i = 1; i < KolArg; i++) {
DS>        prisv<T, T>( Mas, i, va_arg(Args, T) ); // При 2-м проходе (иногда позже) ошибка. Почему?
DS>    }
DS>    va_end(Args);
DS>}

DS>int RazmMasOboznOper = 17;
DS>string* MasOboznOper;
DS>void inic_mas_obozn_oper() {
DS>    sozd(MasOboznOper, RazmMasOboznOper);
DS>    prisv<string>(MasOboznOper, RazmMasOboznOper, "=", "<", "<=", "==", 
DS>            ">=", ">", "!=", "+", "-", "*", "/", "^", "!", 
DS>            "&", "|", "=>", "<=>");
DS>}

DS>void main() {
DS>  inic_mas_obozn_oper();
DS>}


Ошибка в попытке передачи через ellipsis параметров, не являющихся POD-типами. Или даже жестче — ошибка вообще в попытке использования ellipsis. .
В Вашем случае, когда данные однородны (имеют один тип) их можно было просто поместить в последовательность, а её саму передать, например, в виде пары итераторов [начало, конец] или пары [начало, количество_элементов]. Незачем здесь городить ellipsis. Да и вообще стоит стремиться не использовать его во вновь разрабатываемом коде.
Т.е. ошибка в выбранном подходе к решению поставленной задаче.
P.S. А какая именно там ошибка возникает в том месте, которое Вы указали — хз. Места в стандарте C++ конкретного не нашёл, но подозреваю, что передача через ellipsis не POD-типов есть дело нехорошее.
А мне нравится жить :).
Re: Помогите, пожалуйста, найти ошибку в коде
От: _Pete_ Россия  
Дата: 08.11.07 10:12
Оценка:
Здравствуйте, DSblizzard, Вы писали:

prisv<string>(MasOboznOper, RazmMasOboznOper, "=", "<", "<=", "==", 
            ">=", ">", "!=", "+", "-", "*", "/", "^", "!", 
            "&", "|", "=>", "<=>");


не все аргументы передаются как string
Re[2]: Помогите, пожалуйста, найти ошибку в коде
От: Кодт Россия  
Дата: 08.11.07 11:42
Оценка:
Здравствуйте, e-garin, Вы писали:

DS>>template <class T>
DS>>void prisv(T* Mas, int KolArg, T Arg1, T ...) {
.....
DS>>        prisv<T, T>( Mas, i, va_arg(Args, T) ); // При 2-м проходе (иногда позже) ошибка. Почему?
.....
DS>>}

.....

DS>>    prisv<string>(MasOboznOper, RazmMasOboznOper, "=", "<", "<=", "==", 
DS>>            ">=", ">", "!=", "+", "-", "*", "/", "^", "!", 
DS>>            "&", "|", "=>", "<=>");


EG>Ошибка в попытке передачи через ellipsis параметров, не являющихся POD-типами. Или даже жестче — ошибка вообще в попытке использования ellipsis. .

EG>В Вашем случае, когда данные однородны (имеют один тип) их можно было просто поместить в последовательность, а её саму передать, например, в виде пары итераторов [начало, конец] или пары [начало, количество_элементов]. Незачем здесь городить ellipsis. Да и вообще стоит стремиться не использовать его во вновь разрабатываемом коде.
EG>Т.е. ошибка в выбранном подходе к решению поставленной задаче.
EG>P.S. А какая именно там ошибка возникает в том месте, которое Вы указали — хз. Места в стандарте C++ конкретного не нашёл, но подозреваю, что передача через ellipsis не POD-типов есть дело нехорошее.

1. Нестандартный синтаксис prisv(blablabla, T ...) — типизированное отточие.

2. Если компилятор наплевал на T и счёл, что это обычное нетипизированное отточие, то в функцию передаются const char*, а читаются std::string (va_arg(Args,T) где T = string).
Это неопределённое поведение — попросту, неадекватный reinterpret_cast. Что из него получится — никому не известно.
В ATL/MFC были предприняты специальные меры, чтобы const CString совпадал с const char*, поэтому там такие фокусы возможны, хотя это и на грани фола.

3. Если же компилятор умеет обращаться с типизированным отточием — то до какой степени это умение распространяется? Может ли он адекватно передавать не-POD и так же адекватно их читать?
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[3]: Помогите, пожалуйста, найти ошибку в коде
От: elcste  
Дата: 08.11.07 13:03
Оценка:
Здравствуйте, Кодт, Вы писали:

DS>>>void prisv(T* Mas, int KolArg, T Arg1, T ...) {

К>1. Нестандартный синтаксис prisv(blablabla, T ...) — типизированное отточие.

Это, кстати, стандартный синтаксис. Здесь четыре обязательных параметра (последний — неименованный).
Re: Помогите, пожалуйста, найти ошибку в коде
От: Слоноежик  
Дата: 08.11.07 13:20
Оценка:
Здравствуйте, DSblizzard, Вы писали:

[исходный вариант поскипан]

Странно, что использую шаблоны и строки используется string*. Не проще ли еще и вектор использовать.

Да и вообще это мне напоминает странную попытку написать свою версию Inline Container-a от Александреску.
для забивания гвоздя надо выбирать правильный микроскоп.
Re[4]: Помогите, пожалуйста, найти ошибку в коде
От: Кодт Россия  
Дата: 08.11.07 14:39
Оценка: 2 (1)
Здравствуйте, elcste, Вы писали:

К>>1. Нестандартный синтаксис prisv(blablabla, T ...) — типизированное отточие.

E>Это, кстати, стандартный синтаксис. Здесь четыре обязательных параметра (последний — неименованный).

Ай пардон пардон!
Тогда всё вообще встало на свои места.

Первый аргумент из перечня строковых литералов
— был в точке вызова приведён к string,
— некорректное va_start(Args,Arg1) (не на последнем обязательном аргументе) удачно сфокусировало Args на этот первый string
— некорректное va_arg(Args,string) (потому что не POD) удачно получило доступ к string
ну и дальше всё срослось.

Второй аргумент из того перечня
— был передан, как и полагается, в виде const char*
— va_arg(Args,string) обратилось к нему как к const string&
к счастью, оказалось, что первый член string — это const char*, поэтому строку удалось прочесть
Но оператор присваивания уже, скорее всего, сошёл с ума и в Mas[1] записал какую-то фигню.

Третий аргумент
— опять же, const char*
— va_arg(Args,string) в прошлый раз стремительно прыгнул вперёд на sizeof(string), а не на sizeof(const char*)...

Кстати говоря, MasOboznOper — не инициализированный указатель на массив строк.
Так что мы давно уже ездим кому-то по мозгам...
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[5]: Помогите, пожалуйста, найти ошибку в коде
От: DSblizzard Россия  
Дата: 09.11.07 01:03
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Кстати говоря, MasOboznOper — не инициализированный указатель на массив строк.

К>Так что мы давно уже ездим кому-то по мозгам...

В смысле, не инициализирован при объявлении? А зачем, простите за глупый вопрос? После создания он инициализируется, а до создания я его не использую. А если попытаюсь использовать, то это мои проблемы — это будет указывать не на обычный недосмотр, а на логическую ошибку, нужно будет переписать фрагмент по-другому.

"плохо отформатирован". К сожалению, обнаружил после отправки, а возможности редактирования нет. Почему, интересно?
Программировать сложно. Но не программировать еще сложнее.
Re: Помогите, пожалуйста, найти ошибку в коде
От: Centaur Россия  
Дата: 09.11.07 11:21
Оценка: +1
Здравствуйте, DSblizzard, Вы писали:

DS>int RazmMasOboznOper = 17;
DS>string* MasOboznOper;
DS>void inic_mas_obozn_oper() {
DS>    sozd(MasOboznOper, RazmMasOboznOper);
DS>    prisv<string>(MasOboznOper, RazmMasOboznOper, "=", "<", "<=", "==", 
DS>            ">=", ">", "!=", "+", "-", "*", "/", "^", "!", 
DS>            "&", "|", "=>", "<=>");
DS>}


Помимо всех вышеуказанных проблем — пора приучаться называть переменные (функции, типы) по-английски.
Re[6]: Помогите, пожалуйста, найти ошибку в коде
От: Кодт Россия  
Дата: 09.11.07 13:06
Оценка:
Здравствуйте, DSblizzard, Вы писали:

К>>Кстати говоря, MasOboznOper — не инициализированный указатель на массив строк.

К>>Так что мы давно уже ездим кому-то по мозгам...

DS>В смысле, не инициализирован при объявлении? А зачем, простите за глупый вопрос? После создания он инициализируется, а до создания я его не использую.

Нет, он у тебя нигде не присваивается!

0) Определяешь глобальную переменную. Она инициализируется нулём.
1) Передаёшь в sozd(T*,int) её значение — т.е. нуль.
2) sozd() выполняет присваивание локальной переменной, создавая утечку.
3) Передаёшь в prisv(T*,int,T,...) всё тот же нуль.
4) Наконец, внутри prisv() разыменовываешь этот самый нуль операторами [] — вот тебе и стрельба.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[7]: Помогите, пожалуйста, найти ошибку в коде
От: DSblizzard Россия  
Дата: 09.11.07 22:32
Оценка:
Здравствуйте, Кодт, Вы писали:

К>0) Определяешь глобальную переменную. Она инициализируется нулём.

К>1) Передаёшь в sozd(T*,int) её значение — т.е. нуль.
К>2) sozd() выполняет присваивание локальной переменной, создавая утечку.
К>3) Передаёшь в prisv(T*,int,T,...) всё тот же нуль.
К>4) Наконец, внутри prisv() разыменовываешь этот самый нуль операторами [] — вот тебе и стрельба.

В ответе LaptevVV'у я же вроде исправил эту описку.
Программировать сложно. Но не программировать еще сложнее.
Re[2]: Помогите, пожалуйста, найти ошибку в коде
От: DSblizzard Россия  
Дата: 09.11.07 22:35
Оценка:
Здравствуйте, Centaur, Вы писали:

C>Помимо всех вышеуказанных проблем — пора приучаться называть переменные (функции, типы) по-английски.


Ни за Что! На русском гораздо удобнее выражать свои мысли. Даже если бы я знал английский получше, все равно бы писал на русском.
Программировать сложно. Но не программировать еще сложнее.
Re[3]: Помогите, пожалуйста, найти ошибку в коде
От: Max M. Ниоткуда  
Дата: 10.11.07 02:12
Оценка: :)
Да... Размаз-Обознопер рулит конечно...
кстати, хозяйке на заметку:
typedef std::string stroka;
// ...
подпись
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.