Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 13.02.2016, 19:53   #1
Freestyler
 
Регистрация: 01.12.2008
Сообщений: 9
По умолчанию Вылет программы, НО исключительно в релизном .exe

Здравствуйте. Ситуация следующая (опишу всё детально, так что сообщение будет длинным):

C++, Visual Studio 2012, попытка написать свой консольный проект (в перспективе довольно сложный и уже довольно разветвлённый) с использованием ООП. Всё шло довольно неплохо, пока я не обнаружил баг, который меня просто в тупик поставил. Программа падает ТОЛЬКО после сборки exe в конфигурации Release. При отладке всё нормально, exe, собранный в конфигурации Debug, тоже работает как надо, но только не релизная версия. Консоль виснет спустя несколько секунд, затем классическое "Прекращена работа программы".

Сделал лог-систему, определил конкретную проблему: вылет происходит в цикле при попытке выделить память именно для 10 элемента вектора.
Участок кода покажу, но едва ли проблема конкретно в нём, т.к. я даже представить не могу, что в нём может быть неверно:

Код:
std::vector <std::vector <ObjectCell>> cells; // в базовом абстрактном классе
// ...
for (int y = 0; y < height; y++) // в конструкторе производного класса
{
        // std::vector <ObjectCell> temp;
	std::vector <int> temp;

	for (int x = 0; x < width; x++)
	{
		// temp.push_back(ObjectCell(id, x, y, chText[x], textClr));
		temp.push_back(1); // вылет при x == 9
	}
	// cells.push_back(temp);
}
Как видно выше, я заменил вектор temp на интовый, чтобы исключить ошибку, связанную с конструктором ObjectCell(), да и вообще, для упрощения ситуации.

Альтернативный код, который можно было бы использовать для тех же целей:

Код:
cells.resize(height);
for (int y = 0; y < height; y++)
{
	cells[y].reserve(width); // вылет при x >= 2
	
	for (int x = 0; x < width; x++)
	{
		cells[y].push_back(ObjectCell(id, x, y, chText[x], textClr));

	}
}
Не проходит reserve, причём почему-то уже для 2 и более элементов.

Я даже раздобыл и добавил в проект самописную реализацию вектора, чтобы убедиться в конкретной причине ошибки:

Код:
template <typename T> class m_vector
{
private:	
	T *_array;
	int _arraySize;	
public:
	void push_back(T data)
	{
		console.AddLogStroke("Начинаем push_back внутри m_vector");

		T *_result = new T[++this->_arraySize]; // вылет
// ...
Видимо, проблема в утечке памяти, но я уже понятия не имею, что и как исправлять, мне банально не хватает опыта, ну или мозгов.

Что уже было сделано для исправления вылета:

1. try-catch
Использовал следующую обёртку:
Код:
try
{
	cells[y].reserve(width);
}
catch (...)
{
	console.AddLogStroke("!!! Сработало исключение !!!");
	exit(0);
}
Ну и по аналогии с push_back и даже вылетающим new в реализации вектора m_vector. Не знаю, насколько правильно, но эффекта никакого.

2. Пытался воспроизвести ошибку в новом тестовом проекте, убрав абсолютно всё, что не относится непосредственно к проблемному участку кода, воссоздал все необходимые для него классы, сделав их практически пустыми. Ошибка не повторилась, что подтверждает идею о том, что проблема в том коде, который выполняется раньше. Проблема в том, что проект уже достаточно разветвлённый и лично для меня очень сложно постепенно добавлять к тестовому проекту код из оригинала, т.к. одно "цепляется" за другое и я без понятия, как это всё написать с неполным функционалом, но так, чтобы воспроизвести ошибку.

3. Прочёл статью "Как пережить release-версию", понял не слишком много, но некоторые приёмы оттуда применил. В частности - проинициализировал все переменные в соответствующих конструкторах и полностью отключил оптимизацию в release-конфигурации. Ни то, ни другое, как вы понимаете, не помогло.

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

Но вообще, это так, надежда на халяву. По делу вопросы такие - что ещё можно сделать, по какой причине эта ошибка может возникать, учитывая всё вышенаписанное (а то у меня лишь догадки), и какие ещё средства отладки для релизного exe можно применить, чтобы разобраться в проблеме?

Благодарю за потраченное время.
Freestyler вне форума Ответить с цитированием
Старый 13.02.2016, 20:39   #2
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

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

Вот ваша проблема:
int width = wcslen(str);
text = new wchar_t[width];
wcscpy(text, str);

Совет:
Никогда, никогда, НИКОГДА не работайте с указателями напрямую.
waleri вне форума Ответить с цитированием
Старый 13.02.2016, 21:15   #3
Freestyler
 
Регистрация: 01.12.2008
Сообщений: 9
По умолчанию

Чёрт, спасибо. Чувствую себя идиотом - я не понимаю, почему я считал, что завершающий символ включается в возвращаемое wcslen значение, ведь в документации написано обратное. К тому же, я же ведь вообще закомментировал когда-то весь этот участок кода и каким-то образом получил вылет, поэтому был уверен, что это тут ни при чём.
Всего-то int width = wcslen(str) + 1; и всё заработало.

Но совет ваш я приму к сведению. Спасибо огромное.
Freestyler вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Вылет программы при использовании макроса SaLoKiN Microsoft Office Excel 102 03.12.2013 07:07
Windows запускается исключительно с флэшки. Михаил Урвилов Операционные системы общие вопросы 1 25.05.2012 20:08
вылет программы при выводе простого числа (cout) Ciberal Общие вопросы C/C++ 7 27.09.2011 01:51
Вылет программы после завершение kloffelin Общие вопросы C/C++ 3 17.04.2010 20:18
Из программы 1.exe создаем пустой файл 2.exe. Как из программы 1 внести API функции в программу 2? X-LEV-X Общие вопросы Delphi 7 09.03.2010 08:33