Перехлёстывающиеся массивы

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Фоб
Сообщения: 45
Зарегистрирован: 10 ноя 2006, 14:56

10 июн 2008, 01:08

Это просто ужос!

Я 6 часов потратил на поиск ошибки.

И обнаружил ну совсем невменяемую хрень.

Итак, есть 2 класса:

Код: Выделить всё

класс2{
	float* массив2
	void f2(){
		// наращивание массива2
		массив2 = new float[цифра]
	}
}

класс1{
	float* массив1
	класс2 к2.
	void f1(){
		// наращивание массива1
		массив1 = new float[цифра]
	}
}
Кто-нибудь может хотя бы примерно предположить, почему в результате заполнения циферками массива класс1.массив1, нулевой элемент массива класс1.к2.массив2 получает значение типа 1000653463.

Индексация в процедуре заполнения первого массива - абсолютно верная.

Адреса массивов охренительно далеко друг от друга.

Я проверил и перепроверил всё - никаких зацепок, в чём причина. Только иррациональное следствие: пишем в первый массив, и в одном случае из ста сбивается нулевой элемент второго массива.

Операция переноса значений в функциях f1 и f2 - тоже в порядке, я расставлял ловушки везде, где только можно, и однозначно установил место в программе, в котором нулевой элемент сбивается - СРАЗУ ЖЕ после заполнения первого массива.

Конечно, я могу использовать vector вместо массивов, и наверняка фигня исчезнет, но не хочется оставлять эту ошибку непонятой, особенно с учётом 6 часов борьбы с этим привидением.
Аватара пользователя
Romeo
Сообщения: 3091
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

10 июн 2008, 13:13

Уверен, что ты напутыл с размерами или индексами во время заполнения. Выкладывай сюда код полностью. Демагогия - это хорошо, но реальный код - лучше :)
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
airyashov
Сообщения: 416
Зарегистрирован: 02 ноя 2007, 10:31

10 июн 2008, 17:01

Надо полный код смотреть
Фоб
Сообщения: 45
Зарегистрирован: 10 ноя 2006, 14:56

10 июн 2008, 20:49

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

Код: Выделить всё

class promoter{		  		// элемент дерева экспрессии/ингибирования
public:
			
	int* a; 		// тот самый массив, в чей нулевой элемент незаконно вписывают хрень
	int a_size;     
	void add_leaf(int leaf_n){       // процедура наращивания того самого массива а, в чей нулевой элемент попадает хрень
		if (!a_size){
			a_size = 1;
			a = new int[a_size];
			a[0] = leaf_n;	// тут всё нормально записывается - проверял
		}
		else{
			int* temp_a = new int[a_size + 1];
			int i;
			for (i = 0; i < a_size; i++)
				temp_a[i] = a[i];
			temp_a[a_size] = leaf_n;
			delete(a);		// кстати, эта инструкция не лишняя часом?
			a_size++;
			a = new int[a_size];
			for (i = 0; i < a_size; i++){
				a[i] = temp_a[i];
			}
		}
	}

};

class gene{
public:
	vector<promoter> eTree;	
	vector<promoter> iTree;	
    			
	genome* myGenome;       
	gene(int tree_size, int an, genome* g){
		int i;
		myGenome = g;
		for (i = 0; i < tree_size; i++)
			add_random_promoter();	// тут заполняются eTree и iTree
	}
};


class genome{
public:
	float* p;		// когда пишем в этот массив, в а[0] одного из vector<gene> genes (а в нём одного из eTree) пишется хрень
	vector<gene> genes;
	int p_length;	// по умолчанию = 9
	int p_real;		// по умолчанию = 9
	int p_feel;		// по умолчанию = 6
	genome(){};	
	genome(int p_r, int p_f, int rgenes){	
		p_feel = p_f;
		p_real = p_r;
		p_length = p_r;                 
		p = new float(p_length);
		int i;
		for (i = 0; i < rgenes; i++)
			create_random_gene(1 + random(INIT_TREE_SIZE));
	}
	void create_random_gene(int pep_dep = 1){	
		int n = p_feel + random(p_length - p_feel + 1);		
		if (n == p_length){
			p_length++;
			p = new float[p_length];
		}
		genes.push_back(gene(pep_dep, n, this));
	}
	void update_perception(float* obj_p){
		int i;
		for (i = 0; i < p_feel; i++)
			p[i] = obj_p[i];	// !!! цикл №1, после которого в нулевой элемент одного из массивов а пишется хрень; (замечу, что p_feel == 6, что меньше, чем длина массива p, равная 9)
	}
	void genes_work(){
		int i;
		int c_range = p_length - p_feel;	
		float* temp_p = new float[c_range];     
		for (i = 0; i < c_range; i++)
			temp_p[i] = 0;
		for (i = 0; i < genes.size(); i++) {

			int j;
			for (j = 0; j < genes[i].eTree.size(); j++) {
				if (genes[i].eTree[j].a_size) {
					if (genes[i].eTree[j].a[0] > 10) {
						genes[i].eTree[j].a[0] = 1;
					}
				}
			}

			temp_p[genes[i].n - p_feel] = p_or(temp_p[genes[i].n - p_feel], genes[i].work());
		}
		for (i = p_feel; i < p_length; i++) {	//
			p[i] = temp_p[i - p_feel];	// !!! цикл №2, после которого в нулевой элемент одного из массивов а может попасть хрень; 
		}				//
	}
};

Фоб
Сообщения: 45
Зарегистрирован: 10 ноя 2006, 14:56

10 июн 2008, 20:58

Блиииииииииин! Ну надо же! Это, наверное, от непрофессионализма.

Секунду назад выложил этот код, взглянул на появившийся код и взгляд мой упал на строчку

p = new float(p_length);

Скобочки не квадратные..............

Неужели из-за этого я вчера столько мучился :/

Ужос
Аватара пользователя
Romeo
Сообщения: 3091
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

10 июн 2008, 22:26

Угу, похоже.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Хыиуду
Сообщения: 2388
Зарегистрирован: 06 мар 2005, 21:03
Откуда: Москва
Контактная информация:

11 июн 2008, 11:19

[offtop]
Вот за подобные вещи я Си и не люблю. Знает, скотина, что будет все неправильно, но в жизни не признается!
[/offtop]
Искусство программирования - заставить компьютер делать все то, что вам делать лень.
Для "спасибо" есть кнопка "Спасибо" в виде звездочки внизу под ником автора поста.
Аватара пользователя
Romeo
Сообщения: 3091
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

11 июн 2008, 12:44

Хыиуду писал(а):[offtop]
Вот за подобные вещи я Си и не люблю. Знает, скотина, что будет все неправильно, но в жизни не признается!
[/offtop]

Нет, ты не прав. То, что действительно неверно, то репортится, как ошибка. В данном же случае мы наблюдаем допустимую форму записи оператора new. Она называется аллокацией в существующей области памяти. В скобках ожидается поинтер, указывающий на эту область. Естественно p_length не является этим поинтером, потому всё работает криво.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Albor
Сообщения: 482
Зарегистрирован: 06 сен 2004, 13:34
Откуда: Днепропетровск

11 июн 2008, 14:17

Romeo писал(а):Нет, ты не прав. То, что действительно неверно, то репортится, как ошибка. В данном же случае мы наблюдаем допустимую форму записи оператора new. Она называется аллокацией в существующей области памяти. В скобках ожидается поинтер, указывающий на эту область. Естественно p_length не является этим поинтером, потому всё работает криво.

Romeo, разве в скобках ожидается указатель? По моему, данная строка интерпретируется как выделение памяти под переменную типа float, инициализируемую значением типа int. То есть, после выделения памяти, по адресу, помещённому в p будет находится значение, равное p_length
Аватара пользователя
Romeo
Сообщения: 3091
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

11 июн 2008, 15:16

&quot писал(а):Romeo, разве в скобках ожидается указатель? По моему, данная строка интерпретируется как выделение памяти под переменную типа float, инициализируемую значением типа int. То есть, после выделения памяти, по адресу, помещённому в p будет находится значение, равное p_length
Верно говоришь, Albor . Я невнимательно посмотрел на строку. Поинтер на область указывается после new, но до имени типа. Но то, что такой синтаксис позволителен - в этом я прав :)
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ответить