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

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

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 28.02.2011, 13:56   #1
Colder M
Пользователь
 
Регистрация: 28.02.2011
Сообщений: 16
По умолчанию C: free() - ошибка при выполнении

Здравствуйте. Подскажите, как устранить следующую проблему. Сделал перемножение динамических матриц.

Код:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void main()
{
//init
	//attrib
	int m;
	printf("\n Matrix A: num of strings = "); scanf("%d",&m); m--;
	int s;
	printf("\n Matrix A: num of columns = "); scanf("%d",&s); s--;
	int n;
	printf("\n Matrix B: num of columns = "); scanf("%d",&n); n--;
	//matrix A
	int **A;
	A=(int**)calloc(m,sizeof(int*));
	int i;
	for(i=0; i<=m; i++)
		A[i]=(int*)calloc(s,sizeof(int));
	//matrix B
	int **B;
	B=(int**)calloc(s,sizeof(int*));
	for(i=0; i<=s; i++)
		B[i]=(int*)calloc(n,sizeof(int));
	//matrix C
	int **C;
	C=(int**)calloc(m,sizeof(int*));
	for(i=0; i<=m; i++)
		C[i]=(int*)calloc(n,sizeof(int));
//randgen
	srand(time(NULL));
	int j;
	//matrix A
	printf("\n\n Left matrix: ");
	for(i=0; i<=m; i++)
	{
		printf("\n\n");
		for(j=0; j<=s; j++)
		{
			A[i][j]=rand()%128;
			printf("\t%d", A[i][j]);
		}
	}
	//matrix B
	printf("\n\n\n Right matrix: ");
	for(i=0; i<=s; i++)
	{
		printf("\n\n");
		for(j=0; j<=n; j++)
		{
			B[i][j]=rand()%128;
			printf("\t%d", B[i][j]);
		}
	}
//mult
	for(i=0; i<=m; i++)
		for(j=0; j<=n; j++)
			C[i][j]=0;
	//matrix C
	printf("\n\n\n Result matrix: ");
	int k;
	for(i=0; i<=m; i++)
	{
		printf("\n\n");
		for(j=0; j<=n; j++)
		{
			for (k=0; k<=s; k++)
				C[i][j]+=A[i][k]*B[k][j];
			printf("\t%d", C[i][j]);
		}
	}
//clrmem
	for(i=0; i<=m; i++)
	{
		free(A[i]);
		free(C[i]);
	}
	free(A);
	free(C);
	for(i=0; i<=s; i++)
		free(B[i]);
	free(B);
}
Все работает до этапа освобождения памяти (//clrmem), после чего программа завершается с ошибкой (не всегда, для некоторых значений m,n,s выполняется успешно).
Вот сигнатура:
Имя события проблемы: APPCRASH
Имя приложения: MultMatrix.exe
Версия приложения: 0.0.0.0
Отметка времени приложения: 4d6b7b1e
Имя модуля с ошибкой: ntdll.dll
Версия модуля с ошибкой: 6.1.7600.16559
Отметка времени модуля с ошибкой: 4ba9b29c
Код исключения: c0000005
Смещение исключения: 0003285d
Версия ОС: 6.1.7600.2.0.0.256.48
Код языка: 1049
Дополнительные сведения 1: 0a9e
Дополнительные сведения 2: 0a9e372d3b4ad19135b953a78882e789
Дополнительные сведения 3: 0a9e
Дополнительные сведения 4: 0a9e372d3b4ad19135b953a78882e789
Colder M вне форума Ответить с цитированием
Старый 28.02.2011, 14:11   #2
Obey-Kun
Линуксоид
Участник клуба
 
Аватар для Obey-Kun
 
Регистрация: 31.07.2009
Сообщений: 1,403
По умолчанию

Цитата:
C[i]=(int*)calloc(n,sizeof(int));
Можно обходиться без приведения типа. Просто пиши C[i]=calloc(n,sizeof(int));
(это касается только Си, в C++ приводить тип у calloc/malloc уже надо, но кто ж там их использует...)

По-моему, у тебя косяк в том, что везде используется что-то типа
Код:
for(i=0; i<=m; i++)
а должно
Код:
for(i=0; i<m; i++)
Ибо если у тебя A=(int**)calloc(m,sizeof(int*)), то A имеет m элементов — от 0 до m-1. А ты в своих циклах, выходит, рассчитываешь на то, что там элементы идут от 0 до m, но это получается m+1 элементов.
И вот ещё что. Незачем объявлять счётчики (k, i и так далее) заранее. Просто пиши for (int i=0; ........................) { ...... }
Я схожу с ума или это глючит реальность?
Jabber ID: obey@obey.su
Obey-Kun вне форума Ответить с цитированием
Старый 28.02.2011, 14:44   #3
Colder M
Пользователь
 
Регистрация: 28.02.2011
Сообщений: 16
По умолчанию

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

По поводу счетчиков - у меня была мысль локализовать их, но программа сплошь состоит из циклов, поэтому я решил, что объявлять счетчики сразу для всех циклов по мере их необходимости будет рациональнее. Из этих же соображений я хотел поместить выделение памяти под матрицу C после заполнения A и B, но при этом программа завершалась с похожей ошибкой в самых неожиданных местах...

Последний раз редактировалось Colder M; 28.02.2011 в 14:48.
Colder M вне форума Ответить с цитированием
Старый 28.02.2011, 14:50   #4
Obey-Kun
Линуксоид
Участник клуба
 
Аватар для Obey-Kun
 
Регистрация: 31.07.2009
Сообщений: 1,403
По умолчанию

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

Например, тут ошибки нет:
Код:
for(int i = 0; i < 10; ++i) {
    // ...
    for(int i = 0; i < 5; ++i) {
        // ...
    }
    // ...
}
А этот цикл будет выполняться вечно:
Код:
int i;
for(i = 0; i < 10; ++i) {
    // ...
    for(i = 0; i < 5; ++i) {
        // ...
    }
    // ...
}
Цитата:
Спасибо за участие, но дело в том, что у меня значение переменной сразу после ввода уменьшается на 1:
Так это неверно, говорю же.
Код:
printf("\n Matrix A: num of strings = "); scanf("%d",&m); m--
// юзер ввёл 10, теперь m == 9
int **A;
A=(int**)calloc(m,sizeof(int*)); // выделяем под A 9 ячеек
for(i=0; i<=m; i++) // а вот и ошибка. Итерируем от 0 до 9. Но в этом массиве девять элементов, и номер девятого - 8, т.е. итерировать надо от 0 до 8, а иначе программа упадёт
Чтобы не ошибаться, итерацию всегда делайте таким способом:
Код:
for(i=0; i < size_of_array; i++)
Я схожу с ума или это глючит реальность?
Jabber ID: obey@obey.su

Последний раз редактировалось Obey-Kun; 28.02.2011 в 14:57.
Obey-Kun вне форума Ответить с цитированием
Старый 28.02.2011, 15:06   #5
Colder M
Пользователь
 
Регистрация: 28.02.2011
Сообщений: 16
По умолчанию

Большое спасибо за советы, пользуюсь. С понижением переменной я уже разобрался, просто поздно подредактировал пост. Перенес выделение памяти под C куда и хотел, проблема была все в том же счетчике.
Colder M вне форума Ответить с цитированием
Старый 28.02.2011, 15:17   #6
Obey-Kun
Линуксоид
Участник клуба
 
Аватар для Obey-Kun
 
Регистрация: 31.07.2009
Сообщений: 1,403
По умолчанию

Но бога ради, пользуйся этими советам:
1) Вместо D=(int**)calloc(s,sizeof(int*)) пиши просто D=calloc(s,sizeof(int*))
2) Для итераций по массивам вместо for(i=0; i<=s; i++) (где s=real_size_of_arr-1) пиши for(i=0; i < real_size_of_arr; i++)
3) Не объявляй счётчики заранее
Этим правилам (во всяком случае, второму и третьему) в наше время следуют все хорошие программисты на Си.
Я схожу с ума или это глючит реальность?
Jabber ID: obey@obey.su

Последний раз редактировалось Obey-Kun; 28.02.2011 в 15:19.
Obey-Kun вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ошибка при выполнении 123cmp Помощь студентам 4 22.01.2011 23:45
Ошибка при выполнении программы Гурам Общие вопросы Delphi 1 18.11.2010 18:53
Странная ошибка при выполнении okolobaxa Общие вопросы Delphi 2 03.07.2007 00:47
Ошибка при выполнении запроса Elena БД в Delphi 3 14.06.2007 15:13
Ошибка при выполнении запроса Elena БД в Delphi 2 25.05.2007 16:19