Баг в msvc 2010?
От: SaZ  
Дата: 11.11.11 14:53
Оценка:
Следующий код не работает в msvc 2010, но работает в gcc:
(Если убрать ссылку, то всё работает)
#include <stdarg.h>
#include <iostream>

int sum( const int& count, ... )
{
    va_list args;
    va_start( args, count );

    int result = 0;
    for ( int i = 0; i < count; i++ )
        result += va_arg( args, int );
    return result;
}

int main()
{
    std::cout << sum( 3, 1, 2, 3 );
    
    return 0;
}


А как должно быть на самом деле?
Re: Баг в msvc 2010?
От: Сергей Мухин Россия  
Дата: 11.11.11 14:59
Оценка: -1
Здравствуйте, SaZ, Вы писали:

SaZ>Следующий код не работает в msvc 2010, но работает в gcc:

SaZ>(Если убрать ссылку, то всё работает)
SaZ>
SaZ>#include <stdarg.h>
SaZ>#include <iostream>

SaZ>int sum( const int& count, ... )
SaZ>{
SaZ>    va_list args;
SaZ>    va_start( args, count );

SaZ>    int result = 0;
SaZ>    for ( int i = 0; i < count; i++ )
SaZ>        result += va_arg( args, int );
SaZ>    return result;
SaZ>}

SaZ>int main()
SaZ>{
SaZ>    std::cout << sum( 3, 1, 2, 3 );
    
SaZ>    return 0;
SaZ>}
SaZ>


SaZ>А как должно быть на самом деле?


попробуй так (вроде у MS была ошибка с ... после &:

int sum( int count, ... )
---
С уважением,
Сергей Мухин
Re: Баг в msvc 2010?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 11.11.11 15:09
Оценка: 1 (1)
Здравствуйте, SaZ, Вы писали:

Не уверен, что это баг.
Для инициализации va_list нужен адрес последнего фиксированного параметра на стеке, у вас же count передается по ссылке (реально в стеке находится указатель на count), и, когда мы берем адрес count, мы получаем не адрес на стеке, а адрес где размещен count — может на стеке вызывающей функции, может динамической памяти, или где там этот count определен. Имхо, при взятии адреса от ссылки возвращается адрес объекта, а не адрес ссылки — по моим ощущениям, это ближе к стандарту, хотя могу ошибаться. Gcc, возможно, просто "догадался", что вы имели ввиду, но имхо он не прав.
Маньяк Робокряк колесит по городу
Re[2]: Баг в msvc 2010?
От: SaZ  
Дата: 11.11.11 15:19
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:

СМ>попробуй так (вроде у MS была ошибка с ... после &:


SaZ>>(Если убрать ссылку, то всё работает)
Re[2]: Баг в msvc 2010?
От: SaZ  
Дата: 11.11.11 15:21
Оценка:
Здравствуйте, Marty, Вы писали:

M>Не уверен, что это баг.

M>Для инициализации va_list нужен адрес последнего фиксированного параметра на стеке, у вас же count передается по ссылке (реально в стеке находится указатель на count), и, когда мы берем адрес count, мы получаем не адрес на стеке, а адрес где размещен count — может на стеке вызывающей функции, может динамической памяти, или где там этот count определен. Имхо, при взятии адреса от ссылки возвращается адрес объекта, а не адрес ссылки — по моим ощущениям, это ближе к стандарту, хотя могу ошибаться. Gcc, возможно, просто "догадался", что вы имели ввиду, но имхо он не прав.

Я где-то так и думал. Нужно будет почитать про устройство ссылок. Спасибо.
Re: Баг в msvc 2010?
От: k.o. Россия  
Дата: 11.11.11 15:27
Оценка:
Здравствуйте, SaZ, Вы писали:

SaZ>Следующий код не работает в msvc 2010, но работает в gcc:

SaZ>(Если убрать ссылку, то всё работает)

SaZ>А как должно быть на самом деле?


Это UB, поэтому "на самом деле" может происходить что угодно.
Re[2]: Баг в msvc 2010?
От: Masterkent  
Дата: 11.11.11 15:42
Оценка: 34 (2) +1
Marty:

M>Gcc, возможно, просто "догадался", что вы имели ввиду, но имхо он не прав.


А в чём он, собственно, не прав? Неопределённое поведение вполне может совпасть с желаемым. То, что поведение тут неопределённое, явным образом прописано в C++11 — 18.10/3:

The restrictions that ISO C places on the second parameter to the va_start() macro in header <stdarg.h> are different in this International Standard. The parameter parmN is the identifier of the rightmost parameter in the variable parameter list of the function definition (the one just before the ...). [Footnote: Note that va_start is required to work as specified even if unary operator& is overloaded for the type of parmN.] If the parameter parmN is declared with a function, array, or reference type, or with a type that is not compatible with the type that results when passing an argument for which there is no parameter, the behavior is undefined.

Re[2]: Баг в msvc 2010?
От: Сергей Мухин Россия  
Дата: 11.11.11 17:20
Оценка: -2
Здравствуйте, Marty, Вы писали:

M>Не уверен, что это баг.

M>Для инициализации va_list нужен адрес последнего фиксированного параметра на стеке, у вас же count передается по ссылке (реально в стеке находится указатель на count), и, когда мы берем адрес count, мы получаем не адрес на стеке, а адрес где размещен count — может на стеке вызывающей функции, может динамической памяти, или где там этот count определен. Имхо, при взятии адреса от ссылки возвращается адрес объекта, а не адрес ссылки — по моим ощущениям, это ближе к стандарту, хотя могу ошибаться. Gcc, возможно, просто "догадался", что вы имели ввиду, но имхо он не прав.

какой-то бред. Полное не понимание, что передается и как.

Если верить Вашей логике, то и *Count нельзя использовать (т.к. там такой же адрес как и &Count), а это не так.

Здесь имеет место быть просто ошибка MS (довольно старая) и делать какие-либо теоретические выкладки — глупо
---
С уважением,
Сергей Мухин
Re[3]: Баг в msvc 2010?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 11.11.11 17:41
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:

M>>Не уверен, что это баг.

M>>Для инициализации va_list нужен адрес последнего фиксированного параметра на стеке, у вас же count передается по ссылке (реально в стеке находится указатель на count), и, когда мы берем адрес count, мы получаем не адрес на стеке, а адрес где размещен count — может на стеке вызывающей функции, может динамической памяти, или где там этот count определен. Имхо, при взятии адреса от ссылки возвращается адрес объекта, а не адрес ссылки — по моим ощущениям, это ближе к стандарту, хотя могу ошибаться. Gcc, возможно, просто "догадался", что вы имели ввиду, но имхо он не прав.

СМ>какой-то бред. Полное не понимание, что передается и как.

Ну я и писал имхо.
СМ>Если верить Вашей логике, то и *Count нельзя использовать (т.к. там такой же адрес как и &Count), а это не так.
Нет, не так. При взятии адреса указателя будет взят именно адрес указателя, а не адрес адресуемого этим указателем объекта. Можно попробовать — создать 100500 различно вложенных функций, в которые передавать ссылку и брать от нее адрес — думаю, результат будет везде одинаков. И второй вариант — те же 100500 функций, но величина передается по значению или передается указатель — уверен, адрес будет везде разным. Со стандартом в руках не докажу, конечно, возможно и не прав.

СМ>Здесь имеет место быть просто ошибка MS (довольно старая) и делать какие-либо теоретические выкладки — глупо
Маньяк Робокряк колесит по городу
Re[4]: Баг в msvc 2010?
От: Сергей Мухин Россия  
Дата: 11.11.11 18:30
Оценка: -3
Здравствуйте, Marty, Вы писали:

СМ>>какой-то бред. Полное не понимание, что передается и как.

M>Ну я и писал имхо.

СМ>>Если верить Вашей логике, то и *Count нельзя использовать (т.к. там такой же адрес как и &Count), а это не так.

M>Нет, не так. При взятии адреса указателя будет взят именно адрес указателя, а не адрес адресуемого этим указателем объекта. Можно попробовать — создать 100500 различно вложенных функций, в которые передавать ссылку и брать от нее адрес — думаю, результат будет везде одинаков. И второй вариант — те же 100500 функций, но величина передается по значению или передается указатель — уверен, адрес будет везде разным. Со стандартом в руках не докажу, конечно, возможно и не прав.

&int Count и *int Count передаются абсолютно одинаково уж в MS точно. для 32бит пихается адрес целого в стек.

т.е. все ваши слова в топку.
---
С уважением,
Сергей Мухин
Re[5]: Баг в msvc 2010?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 11.11.11 19:16
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:

СМ>>>Если верить Вашей логике, то и *Count нельзя использовать (т.к. там такой же адрес как и &Count), а это не так.

M>>Нет, не так. При взятии адреса указателя будет взят именно адрес указателя, а не адрес адресуемого этим указателем объекта. Можно попробовать — создать 100500 различно вложенных функций, в которые передавать ссылку и брать от нее адрес — думаю, результат будет везде одинаков. И второй вариант — те же 100500 функций, но величина передается по значению или передается указатель — уверен, адрес будет везде разным. Со стандартом в руках не докажу, конечно, возможно и не прав.

СМ>&int Count и *int Count передаются абсолютно одинаково уж в MS точно. для 32бит пихается адрес целого в стек.

С этим утверждением не буду спорить, так как оно соответствует реальному положению вещей. Единственно, амперсанд не там поставлен.

СМ>т.е. все ваши слова в топку.

Ну может и в топку, но операция взятия адреса для параметра-ссылки и для параметра-указателя даст разные значения — в первом случае будет адрес реального размещения величины, во втором — адрес указателя на место реального размещения величины. Если считаете, что я не прав ( а я прав ), то приведите код, который опровергает мои утверждения.
Маньяк Робокряк колесит по городу
Re[6]: Баг в msvc 2010?
От: Dzirt2005  
Дата: 11.11.11 20:15
Оценка:
Здравствуйте, Marty, Вы писали:

[skip]
M>Ну может и в топку, но операция взятия адреса для параметра-ссылки и для параметра-указателя даст разные значения — в первом случае будет адрес реального размещения величины, во втором — адрес указателя на место реального размещения величины.
Я правильно понимаю, что во втором случае размер этого самого указателя вычислить можно, а в первом — нельзя?
Re[6]: Баг в msvc 2010?
От: Сергей Мухин Россия  
Дата: 11.11.11 20:19
Оценка: -2
Здравствуйте, Marty, Вы писали:


СМ>>&int Count и *int Count передаются абсолютно одинаково уж в MS точно. для 32бит пихается адрес целого в стек.

M>С этим утверждением не буду спорить, так как оно соответствует реальному положению вещей.
отлично

> Единственно, амперсанд не там поставлен.

ага

СМ>>т.е. все ваши слова в топку.

M>Ну может и в топку, но операция взятия адреса для параметра-ссылки и для параметра-указателя даст разные значения — в первом случае будет адрес реального размещения величины, во втором — адрес указателя на место реального размещения величины. Если считаете, что я не прав ( а я прав ), то приведите код, который опровергает мои утверждения.

я этого никогда не утверждал.
Но нам не надо получать этот адрес, нам надо адрес следующего параметра в каком-то массиве (например в стеке), компилятор мог бы подсуетиться и вычислить это сам, не обращая внимания на тип Count. Но стандарт этого не требует.
---
С уважением,
Сергей Мухин
Re[7]: Баг в msvc 2010?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 11.11.11 20:41
Оценка:
Здравствуйте, Dzirt2005, Вы писали:

M>>Ну может и в топку, но операция взятия адреса для параметра-ссылки и для параметра-указателя даст разные значения — в первом случае будет адрес реального размещения величины, во втором — адрес указателя на место реального размещения величины.

D>Я правильно понимаю, что во втором случае размер этого самого указателя вычислить можно, а в первом — нельзя?
Я вас наверно неправильно понимаю, но я вас не понимаю ;
Размер указателя значения не имеет. Мы пытаемся получить не размер указателя, а адрес на стеке, от которого будем отсчитывать адреса аргументов, переданых через ... И в случае ссылки, мы получаем не адрес аргумента на стеке, а адрес объекта, на который ссылаемся.
Маньяк Робокряк колесит по городу
Re: Баг в msvc 2010?
От: Masterkent  
Дата: 11.11.11 22:01
Оценка: 1 (1)
SaZ:

SaZ>Следующий код не работает в msvc 2010, но работает в gcc:


Принципиальное отличие реализации va_start и va_arg у VC++ и GNU C++ состоит в том, что реализация у VC++ пытается получить адрес того места в памяти, на которое ссылается выражение, переданное вторым аргументом у va_start, для того чтобы потом на основе этого адреса отсчитывать адреса дополнительных аргументов функции (как тут уже описал Marty), в то время как у GNU C++ для получения адресов дополнительных аргументов функции привлекаются свои собственные встроенные операторы (реализуемые компилятором, а не библиотечными средствами), которых мало интересует, что там передали вторым аргументом va_start (см. наглядный пример) — компилятор сам в состоянии определить всё, что нужно для правильной работы, без подсказок.
Re: Баг в msvc 2010?
От: Uzumaki Naruto Ниоткуда  
Дата: 12.11.11 05:44
Оценка: -1 :)))
Здравствуйте, SaZ, Вы писали:

SaZ>Следующий код не работает в msvc 2010, но работает в gcc:

SaZ>(Если убрать ссылку, то всё работает)
SaZ>
SaZ>#include <stdarg.h>
SaZ>#include <iostream>

SaZ>int sum( const int& count, ... )
SaZ>{
SaZ>    va_list args;
SaZ>    va_start( args, count );

SaZ>    int result = 0;
SaZ>    for ( int i = 0; i < count; i++ )
SaZ>        result += va_arg( args, int );
SaZ>    return result;
SaZ>}

SaZ>int main()
SaZ>{
SaZ>    std::cout << sum( 3, 1, 2, 3 );
    
SaZ>    return 0;
SaZ>}
SaZ>


SaZ>А как должно быть на самом деле?


va_end(args); где? стек съедит


void PrintFloats ( int amount, ...)
{
int i;
double val;
printf ("Floats passed: ");
va_list vl;
va_start(vl,amount);
for (i=0;i<amount;i++)
{
val=va_arg(vl,double);
printf ("\t%.2f",val);
}
va_end(vl);
printf ("\n");
}

int main ()
{
PrintFloats (3,3.14159,2.71828,1.41421);
return 0;
}


 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.