LINUX.ORG.RU

Любовь к C++. Как бороться с собственной невнимательностью.


1

2

Как я люблю этот язык. Всего лишь из-за одного лишнего символа в описании членов класса я убил на отдладку более 6 часов.

/** @brief Задание для отправки много авторок */
class CCrShareSender : public boost::enable_shared_from_this<CCrShareSender> {
public:
	CCrShareSender(QList<CrShare>& a_shares, CAdminWidget* a_widget);
	~CCrShareSender();
	/** @brief Отправить все */
	sequence::_void sendAll();
private:
	CTaskModel m_model;					///< Модель вывода
	QList<CrShare>& m_shares;			///< Оставшиеся шары

В последней строчку случайно появился &.

А как вы ловите такие ошибки? Кроме долгого вхождения в ДЗЕН

★★★★

Ответ на: комментарий от namezys

убудет. ибо это проверка в runtime

cat ./1.cpp && g++ -O3 ./1.cpp && time ./a.out
#include <cstdio>
#include <cstdlib>
#include <list>

int foo( std::list<int>* plist )
{
	if( !plist )
		return 0; // throw etc.

	int s = 0;

	std::list<int>::iterator it;
	for( it = plist->begin() ; it != plist->end() ; ++it )
		s += *it;

	return s;
}

int main( void )
{
	std::list<int> list;
	list.push_back( 1 );
	list.push_back( 2 );
	list.push_back( 3 );

	int s = 0;

	for( size_t i = 0 ; i < 10000000 ; ++i )
		s += foo( &list );

	printf( "%d\n", s );
}

60000000

real	0m0.037s
user	0m0.036s
sys	0m0.000s
cat ./1.cpp && g++ -O3 ./1.cpp && time ./a.out
#include <cstdio>
#include <cstdlib>
#include <list>

int foo( std::list<int>* plist )
{
//	if( !plist )
//		return 0; // throw etc.

	int s = 0;

	std::list<int>::iterator it;
	for( it = plist->begin() ; it != plist->end() ; ++it )
		s += *it;

	return s;
}

int main( void )
{
	std::list<int> list;
	list.push_back( 1 );
	list.push_back( 2 );
	list.push_back( 3 );

	int s = 0;

	for( size_t i = 0 ; i < 10000000 ; ++i )
		s += foo( &list );

	printf( "%d\n", s );
}

60000000

real	0m0.040s
user	0m0.036s
sys	0m0.000s

убудет, но настолько мало - что попадет в «погрешность»

aho
()
Ответ на: комментарий от gandjubas

Шаблон? Их ещё нехватало. Я о том, что писать дефайны в C надо, а в C++ лучше не увлекаться изобретением нового языка. Итак полно конструкций. Инлайн функцию хотя бы что ли.

anonymous
()
Ответ на: комментарий от yoghurt

> Для этого существует assert

void assert (int expression);

Evaluate assertion

If the argument expression of this macro with functional form compares equal to zero (i.e., the expression is false), a message is written to the standard error device and abort is called, terminating the program execution. http://www.cplusplus.com/reference/clibrary/cassert/assert/

Вы не про этот ассерт, часом? Вам точно нужно «terminating the program execution» по любому поводу? Сурово.

gandjubas
()
Ответ на: комментарий от anonymous

> Инлайн функцию хотя бы что ли.

Не томи, приведи уже свой код с эквивалентной функциональностью и удобством использования.

gandjubas
()
Ответ на: комментарий от anonymous

> Указатели в принимающей функции надо всегда (!) проверять на валидность

Вот это онанизм так онанизм!

Не подскажешь открытые проекты, где такие указателедрочеры тусуются?

LamerOk ★★★★★
()
Ответ на: комментарий от anonymous

> А они тут есть?

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

gandjubas
()
Ответ на: комментарий от LamerOk

> Не подскажешь открытые проекты, где такие указателедрочеры тусуются?

sqlite, например, там не только на NULL проверяется, но и «магические» числа используются, чтоб удостоверится в верности указателя

aho
()
Ответ на: комментарий от LamerOk

GObject проверяет кажись. Давненько не смотрел

vertexua ★★★★★
()
Ответ на: комментарий от yoghurt

> Да, про него. Подобные вещи надо выявлять на этапе тестирования

Это если у вас недопустимы нулевые указатели впринципе, тогда да, это баг.

gandjubas
()
Ответ на: комментарий от gandjubas

> Делай как правильно, и тупи 6 часов.

Если ты по ссылке в функу сунул кривой объект, то возникает вопрос: откуда ты его взял?

namezys ★★★★
() автор топика
Ответ на: комментарий от aho

> убудет, но настолько мало - что попадет в «погрешность»

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

namezys ★★★★
() автор топика
Ответ на: комментарий от namezys

> Мне нравится использование ссылок именно за то, что подразумевается их безгрешность

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

aho
()
Ответ на: комментарий от namezys

> Если ты по ссылке в функу сунул кривой объект, то возникает вопрос: откуда ты его взял?

Можно подробнее, о чём идёт речь?

gandjubas
()
Ответ на: комментарий от gandjubas

В основном ссылки используются для передачи аргументов. Иногда в качестве алиасов. Изредко для хитрой работы со стековым объектом.

Это все вполне валидное безопасное использование. В отличае от попытки сохранять ссылку на какой-то объект где-то. Тут те же грабли, что и с указателем.

namezys ★★★★
() автор топика
Ответ на: комментарий от aho

Посмотрел. Ничего подобдного. Может, где-то и проверяют, но во всём десятке просмотренных функций никто никакие указатели ни на что не проверяет.

LamerOk ★★★★★
()
Ответ на: комментарий от aho

Ну как получить битую ссылку? Создать объект, взять ссылку на него и потом объект грохнуть? Ну тут и указатель тебя не спасет.

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

namezys ★★★★
() автор топика
Ответ на: комментарий от namezys

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

Что значит «подразумевается»? Кем «подразумевается»?

LamerOk ★★★★★
()
Ответ на: комментарий от namezys

> В отличае от попытки сохранять ссылку на какой-то объект где-то. Тут те же грабли, что и с указателем.

Речь о том, что в месте вызова/присвоения и у ссылки и у объекта (на стэке или ещё где) написание одно, а семантика разная. Это есть грубый просчёт дизайнеров С++ (если не сказать - диверсия). Указатели же лишены этого недостатка и ты никогда в коде не перепутаешь указатель и сам объект (символы «*», «&» тебе об этом как бы намекнут в месте вызова/использования указателя). А если перепутаешь, то компилятор намекнёт.

gandjubas
()
Ответ на: комментарий от LamerOk

> Что значит «подразумевается»? Кем «подразумевается»?

ими. в отличие от ссылок у них нет состояние, когда они невалидны

namezys ★★★★
() автор топика
Ответ на: комментарий от aho

Посмотрел. Ничего подобдного

посмотри внимательно на sqlite3_close, sqlite3_finalize, sqlite3_exec, sqlite3SafetyCheckOk и т.д.

int sqlite3_close(sqlite3 *db){
   HashElem *i;                    /* Hash table iterator */
   int j;
 
   if( !db ){
     return SQLITE_OK;
   }
...
SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){
  int rc;
  if( pStmt==0 ){
    /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL
    ** pointer is a harmless no-op. */
    rc = SQLITE_OK;

Где тут проверка на валидность?

LamerOk ★★★★★
()
Ответ на: комментарий от gandjubas

> Не понимай. Только потом не плачь про 6 часов.

Проблемы то была не в использовании ссылок

namezys ★★★★
() автор топика
Ответ на: комментарий от namezys

> Проблемы то была не в использовании ссылок

Это тебе так кажется, потому что ты ничего страшного в их использовании не видишь. А я знаю как оно бывает а главное почему. Поэтому у меня даже с бодуна не получится «нечаянно» объявить ссылку вместо переменной.

gandjubas
()
Ответ на: комментарий от namezys

Ничё не ладно. Арифметика заранее просчитывается, а не на автомате ляпается, а потом ещё в пошаговой отладке это хорошо видно где чего и сколько - практически мгновенно, в отличии от адресов там всяких и ссылок.

gandjubas
()
Ответ на: комментарий от namezys

> какое состояние указателя является невалидным?

Ты, наверное, хотел спросить про ссылки?

Когда ссылка указывает на несуществующий объект. (К.О.)

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

Ну когда и указатель указывает на такой же объект - тоже плохо.

И в обоих случаях недетектируемо

namezys ★★★★
() автор топика

Как мне кажется, тут может помочь лишь тренирока внимательности. В своё время тоже очень много времени приходилось тратить на такие глупости, поэтому было решено просто не торопиться и хорошенько думать, когда пишешь код. На удивление, очень помогло.

Kirakishou
()
Ответ на: комментарий от Kirakishou

> просто не торопиться и хорошенько думать

Правильно. Мальчик просто еще неопытный, научится.

anonymous
()
Ответ на: комментарий от Kirakishou

я таких глупых ошибок уже несколько лет не совершал

нервы, нервы

namezys ★★★★
() автор топика
Ответ на: комментарий от Kirakishou

> и хорошенько думать, когда пишешь код
Т.е, вначале подумать, а затем писать код, как в хаскеле, таки нельзя?

quantum-troll ★★★★★
()
Ответ на: комментарий от quantum-troll

Извращений, собственно, только два: хоккей на траве и балет на льду.

namezys ★★★★
() автор топика

Кстать, а что тут можно намезису было бы посоветовать, чтобы избежать извращения с C++? Вот он пишет, что-то с гуйней и производительное.

Намезис, почему именно C++?

anonymous
()

Да никак. Это нормально. Нет на свете 100-процентных гарантий... )

kiverattes ★☆
()

> А как вы ловите такие ошибки? Кроме долгого вхождения в ДЗЕН

Я не пишу на Си++.

anonymous
()
Ответ на: комментарий от anonymous

> Вот он пишет, что-то с гуйней и производительное.

почему производительное?

Намезис, почему именно C++?

Ну я его знал тогда, когда это началось + желание заказчика. В общем-то, не так и страшно полуичлось

namezys ★★★★
() автор топика
Ответ на: комментарий от namezys

> не вижу, чем жаба лучше.

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

А .NET это только MS. А я работаю под unix

С разморозкой. Mono же.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.