LINUX.ORG.RU

Прошу подсказки по коду С/С++

 ,


0

1

Здравствуйте. Посмотрите, пожалуйста, свежим профессиональным взглядом. Вот это вот:

void LogError(int iErrorNum, const char *cInputString){
	char *cBuffer=new char[255];
	time_t *stmLocalTime_t=new time_t;
	time(stmLocalTime_t);
	tm *stmLocalTime;
	stmLocalTime=localtime(stmLocalTime_t);
	sprintf(cBuffer,"echo \"%d/%d/%d - %d:%d:%d ",stmLocalTime->tm_mday,stmLocalTime->tm_mon+1,
											stmLocalTime->tm_year+1900,stmLocalTime->tm_hour,
											stmLocalTime->tm_min,stmLocalTime->tm_sec);
	if(iErrorNum==0){
		sprintf(cBuffer+strlen(cBuffer),cInputString);
	}else{
		switch(iErrorNum){
			case 0:
				break;
			default:
				sprintf(cBuffer+strlen(cBuffer),"%s",strerror(errno));
				break;
		}
	}
	sprintf(cBuffer+strlen(cBuffer),"\" >> run.log");
	system(cBuffer);
}
При втором вызове (первый раз проходит без проблем, до третьего не доходит) падает (и дебаггер не ловит) на одной из строк - time(stmLocalTime_t);, stmLocalTime=localtime(stmLocalTime_t); или одном из sprintfов в cBuffer. Видимо, ошибка при работе с памятью и, думаю, очевидная, но взгляд замылился, не могу понять, в чём дело. Подскажите, пожалуйста?



Последнее исправление: beastie (всего исправлений: 2)

Сходу и не скажешь, но так:

sprintf(cBuffer+strlen(cBuffer),cInputString);

Никогда не делай. Только литералы!

anonymous
()

не могу понять, в чём дело

Очевидно, занимаетесь не своим делом.

Вот это:

if(iErrorNum==0){
  ...
}else{
	switch(iErrorNum){
		case 0:
			break;
		default:
			...
	}
}
ставит диагноз получше, чем даже логирование строки через вызов echo посредством system.

eao197 ★★★★★
()
Ответ на: комментарий от post-factum

Кхм... Я думал, для использования в следующем вызове требуется инициализировать указатель, выделив память для следующего вызова:

time(stmLocalTime_t);

Иначе time() сработает по неопределённому адресу и код будет ещё более неработающим. Потому это там и написал.

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

Госсподи что за глупости вы пишете? Это не ставит диагноз, это заготовка под последующие кейсы 1, 2, и так далее, и 0 там лишь для того, чтобы было видно, куда писать... И, кроме того, я ещё не решил, что там использовать, if или switch...

Простите, есть кто-то, кто сможет помочь, а не болтать о том, что не спрашивают? Заранее спасибо.

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

Только литералы!

Сходу и не скажешь, но так:

sprintf(cBuffer+strlen(cBuffer),cInputString);

Никогда не делай. Только литералы! anonymous (12.06.2015 11:03:03)

Спасибо за совет, я прислушаюсь, хотя и не совсем понимаю, чем плоха конструция, ведь как поётся в песне, при контроле параметров "... and nothing can possibly go wrong!" :)

А вот то, что с «ходу и не скажешь» - это совсем печально...

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

Будет очень плохо, я понял. Спасибо, что объяснили, сделаю по-другому. По сути вопроса тоже ничего не видите? :(

nimzovich
() автор топика
Ответ на: комментарий от no-such-file

Ччччёрт... Как хорошо, что я сюда обратился...

nimzovich
() автор топика

не особо вникая:
если LogError(int iErrorNum, const char *cInputString)
то может стоит тупо задефайнить все нужные ошибки, и тогда можно будет все сократить к LogError(ERROR_SOME_BLABLA)
а внутри брать ошибку по номеру и добавлять время (get_time_to_log() + get_error(iErrorNum)) (и че там еще нужно)

anTaRes ★★★★
()

падает (и дебаггер не ловит)

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

И эта, не надо выделять память в куче, а потом её бросать. Лучше вообще на стеке всё выделять в данном коде, может тогда и отладчик что-то осмысленное покажет.

no-such-file ★★★★★
()
Ответ на: комментарий от nimzovich

time_t t = time( 0 ); tm *stm = localtime( &t ) ... man strcat() man strftime() и нафига switch внутри else{}?

sigurd ★★★★★
()
Последнее исправление: sigurd (всего исправлений: 1)
Ответ на: комментарий от anTaRes

Да-да, там же есть заготовка под «задефайнить все логи», вон какой-то агрессивный молодой человек уже, не поняв это, уже поставило мне диагноз.

nimzovich
() автор топика
Ответ на: комментарий от no-such-file

И эта, не надо выделять память в куче, а потом её бросать. Лучше вообще на стеке всё выделять в данном коде, может тогда и отладчик что-то осмысленное покажет.

Я почему-то постеснялся и из кода убрал вот такие строки перед последней строчкой: // delete [] cBuffer; // delete stmLocalTime_t; с раскомментированными результат тот же :(

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

это заготовка под последующие кейсы 1, 2, и так далее, и 0 там лишь для того, чтобы было видно,

Про диагнозы больше не стоит.

Скажите, это вам по условиям задачи требуется использовать echo и system()? Или же требуется просто отформатированную строку с таймстемпом в run.log записать?

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

Бегло почитав по теме, обнаружил только этот способ и нашёл его более быстрым, в отличии от написания собственного велосипеда с непосредственной работой с файлами через fopen() и тем более быстрым, чем изучение библиотек, в которых такая работа с логами, несомненно, есть. И использовал в качестве костыля.

Да, мне нужны логи этапов выполнения программы. Никаких условий нет, делаю всё для себя.

Про диагнозы больше не стоит.

Спасибо, ибо тоже нахожу это глупым: ставить диагнозы, не будучи знакомым ни с человеком, ни с обстоятельствами.

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

быстрым, в отличии от написания собственного велосипеда с непосредственной работой с файлами через fopen()

Но как? fopen+fprintf и никаких strlen, адресной арифметики и возможности вылезти за границы буфера.

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

И, кстати, программа на С или всё-таки на С++?

Программа на С+. Как на «рунглише», классы есть инкапсуляции ради, а программа на С. Как-то так. Я, как та пчела, уже начинаю догадываться, что ошибка вне этой функции, раз столько умных людей не смогли ничего разглядеть :(

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

Но как? fopen+fprintf и никаких strlen, адресной арифметики и возможности вылезти за границы буфера.

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

Да, ещё заметил, что cBuffer выделяется в первый проход по адресу 0x804b008, во второй проход 0xz804b5b8, память по адресу 0x804b008 изменена (видимо, из другого места программы). А вот stmLocalTime почему-то выделяется по адресу 0xb7e7e6a0 и второй раз по 0xb7d18b70.

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

Бегло почитав по теме, обнаружил только этот способ и нашёл его более быстрым, в отличии от написания собственного велосипеда с непосредственной работой с файлами через fopen() и тем более быстрым, чем изучение библиотек, в которых такая работа с логами, несомненно, есть. И использовал в качестве костыля.

Спасибо, вы в очередной раз сделали мой день.

Да, мне нужны логи этапов выполнения программы. Никаких условий нет, делаю всё для себя.

Ну тогда делайте хотя бы вот так:

#include <fstream>
#include <ctime>
#include <cstring>
#include <cerrno>

void log_error( int error_code, const char * description = nullptr )
{
	using namespace std;

	ofstream log_file( "run.log", ios_base::app );
	if( !log_file )
		throw runtime_error( "log file cannot be opened" );

	time_t current_time = time( nullptr );
	char timestamp[ 64 ];
	if( !strftime( timestamp, sizeof(timestamp),
			"%d/%m/%Y - %H:%M:%S", localtime( &current_time ) ) )
		throw runtime_error( "strftime failed" );

	log_file << timestamp << " "
			<< (error_code ? strerror( error_code ) :
					(description ? description : "<NO DESCRIPTION>"))
			<< endl;
}

int main()
{
	log_error( 0, "just a test message" );
	log_error( EACCES, "" );
	log_error( EBUSY );
	log_error( 0 );
}
А еще лучше — изучите таки матчасть и выберите одну из готовых библиотек логирования для C++. Поискать можно здесь или здесь

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

Простите, что в очередной раз об этом говорю, но если человек пишет что-то вроде:

if( 0 == x ) {...}
else if( 0 == x ) {}
else {...}
То проблемы у этого человека с ДНК и программирование ему противопоказано от слова совсем.

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

Простите, что в очередной раз об этом говорю, но если человек пишет что-то вроде:

Я извиняю, вы просто невнимательны. Я уже ответил, зачем это сделано. Это как смотреть на кусок железной руды и настойчиво объяснять ГИПу, что его металлическое изделие из легированной стали очень грязное и рассыпется, если к нему что-то попытаться прикрепить. И не грубите, пожалуйста, может, вам валерьяночки попить?

Ну тогда делайте хотя бы вот так:
А еще лучше — изучите таки матчасть и выберите одну из готовых библиотек логирования для C++. Поискать можно здесь или здесь

Большое спасибо, разберусь, что к чему.

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

Ошибка обнаружена, она действительно была там, где вы мне косвенно и посоветовали искать: вне функции. Эта фукнкция запускалась в одном из потоков, все потоки работают стабильно, но вчера перед завершением работы я убрал заглушку while(1) из сновного потока процесса, вследствие чего процесс завершался, соответственно, завершая все потоки без всяких упоминаний об ошибках. Да, это было глупо, но я с удовольствием и в следующий раз покажусь глупым перед всеми и заслужу ещё несколько эпитетов, если при этом получу столько полезной информации!

Begemoth no-such-file anonymous sigurd queen3 anTaRes eao197, большое спасибо, друзья, вы очень помогли!

nimzovich
() автор топика

С/С++

А можно впредь так не писать? Это все равно что написать Ада/Java

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от nimzovich

В гугле. Перед тем, как писать велосипед, можно хотя бы бегло посмотреть первые две страницы выдачи. А вдруг уже кто-то подобное давно сделал?

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

Что-то как-то уныло у вас шутить получается, лучше уж не пытаться, чем так... ну не важно, короче :)

Увидимся в следующих темах.

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

ну вот же

time_t *stmLocalTime_t=new time_t;

учись читать чужой код

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