[C] портится память. как найти почему?

velet25

В программе создаётся динамический массив динамических массивов double.
В конце программы при попытке сделать free для внутренних массивов вылетает ошибка:
DAMAGE: after Normal block (#48) at 0x004401D0.
Что это значит? Что я не так делаю?:(

velet25

пример:
.................
int i;
double** Q;
Q=(double**) malloc(5*sizeof(double*;
for (i=0; i<5; i++)
Q[i]=(double*) malloc(4*sizeof(double;
.................
free(Q[1]); - тут вылетает ошибка! почему?

Helga87

а что находится во втором многоточии? после беглого осмотра ошибка в приведенном куске не найдена

Ivan8209


.................
int i;
double** Q;
Q=(double**) malloc(5*sizeof(double*;
for (i=0; i<5; i++)
Q[i]=(double*) malloc(4*sizeof(double;
................. <---------------------------- Здесь
free(Q[1]); - тут вылетает ошибка! почему?

А ты уверен, что в отмеченном месте не происходит записи вне
индексов выделенного массива?
---
...Я работаю антинаучным аферистом...

velet25

уверен... ошибка происходит именно на шаге free.
как перевести на русский то, что он выдаёт при ошибке (см. первый пост)?

Dasar

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

disna

как перевести на русский то, что он выдаёт при ошибке (см. первый пост)?
Segmentation fault?

velet25

странно, потому что к моменту выполнения этой команды Q[1] - нормальный массив, все элементы которого просматриваются. А никакого другого участка памяти эта команда вроде не должна касаться...
и вообще, разве можно запортить память так, чтобы программа продолжала работать?

Dasar

какой-нибудь такой кусок

double * q = (double*)malloc(n * sizeof(double;
double * q2 = (double*)malloc(n * sizeof(double;
for (int i = 0; i <= n; ++i)
q[i] = 0;

будет отлично работать
а падать уже будет на free q2;

Helga87

выкладывай всю программу, не томи

Ivan8209

> И вообще, разве можно запортить память так, чтобы
> программа продолжала работать?
Здрасьте!
Разумеется, можно.
Про это всякие bugtraq-и пишут, как можно запортить память так,
чтобы программа продолжала работать, но не так, как предполагалось.
> странно, потому что к моменту выполнения этой
> команды Q[1] - нормальный массив, все элементы
> которого просматриваются. А никакого другого
> участка памяти эта команда вроде не должна
> касаться...
Ключевое слово --- "вроде".
---
...Я работаю антинаучным аферистом...

velet25

почему? потому что туда ничего не записали?..

velet25

ага, 450 строк
кстати, в приведенном примере программа бы вылетела уже на последней стадии цикла, т.к. q[n] - незааллоченное место (там n элементов, значит максимальный индекс n-1 правильно?

Helga87

ага, 450 строк
сделай .zip архив и зааплодь на форум. Проблема найдется на порядок быстрее, чем при текущем подходе.

Dasar

> правильно?
нет, не правильно
место за массивом q тоже залочено, но уже под массив q2

buka

первая мысль — в Q[1] записал какой-нибудь отстой

velet25

прикольно, сейчас посмотрю на предмет ошибок такого типа, спасибо!

velet25

Кстати, насколько необходимо вообще освобождать память в конце работы приложения?:)

Ivan8209

Нисколько.
Память всё равно освободится при выходе.
---
...Я работаю антинаучным аферистом...

Slavaga

 
насколько необходимо вообще освобождать память в конце работы приложения

 
Крайне желательно!

Ivan8209

Идиотская подсказка.
Так ты никогда не найдёшь выход за границы массива,
только если тебе очень повезёт.
---
"Vyroba umelych lidi, slecno, je tovarni tajemstvi."

evgen5555

Убери в свойствах проекта Runtime warnings нахрен, раз такой джедай и во всём уверен :-)

Slavaga

Хотя.. ты прав. Здесь немного другой случай

Dasar

> Кстати, насколько необходимо вообще освобождать память в конце работы приложения?:)
лучше освобождать, чтобы как раз было проще найти такие ошибки и утечки памяти

SPARTAK3959

Один из способов найти выходы за границы массива - переписать все на вектор (если все довольно легко переписывается).

nikita270601

Один из способов найти выходы за границы массива - переписать все на вектор (если все довольно легко переписывается).
Вроде бы тут C.

Realist

Как тут уже тебе писали, ошибка почти точно в том, что ты выходишь за границы массива, так что падение программы — не проблема, а следствие проблемы (ошибки где-то раньше).
Танец с бубном:
Попробуй поменять размерности массивов, тогда программа может выпасть раньше, будет проще отладить.
Перед каждым обращением к массиву поставь проверку, что индекс не выходит за диапазон (assert тебе в помощь).
А если все-таки это С++, перепеши на std::vector

Ivan8209

>> Кстати, насколько необходимо вообще освобождать
>> память в конце работы приложения?:)
> лучше освобождать, чтобы как раз было проще найти
> такие ошибки и утечки памяти
Чтобы проще было искать, надо освобождать память не в конце
работы приложения, а сразу же, как только память перестаёт
использоваться.
---
...Я работаю антинаучным аферистом...

Dasar

согласен

shlyumper

Вопспользуйся ElectricFence или чем-нибудь аналогичным.

Marinavo_0507

> Вопспользуйся ElectricFence или чем-нибудь аналогичным.
Нет бы посоветовать книжку по основам программирования почитать.

Ivan8209

Ты не читал Ерсуб "про математиков"?
---
...Я работаю антинаучным аферистом...

shlyumper

Тогда уж лучше советовать сразу учить Lisp™

Marinavo_0507

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

Ivan8209

Lisp не является товарным знаком.
---
...Я работаю антинаучным аферистом...

shlyumper

Чувство юмора тоже свойственно не всем форумчанам. И чо?

Ivan8209

Хаскелл популярнее.
---
...Я работаю антинаучным аферистом...

shlyumper

Lisp фуднаментальнее.

Ivan8209

Haskell функциональнее.
---
...Я работаю антинаучным аферистом...

shlyumper

Спорное утверждение. Не существует такой функциональности Haskell, которую нельзя было бы реализовать на Lisp.

Ivan8209

В лиспе слишком просто писать императивно.
---
...Я работаю антинаучным аферистом...

shlyumper

А в Хаскеле, когда возникает необходимость, приходится это делать через неестественные абстракции.

Ivan8209

Верно. Поэтому хаскелл функциональнее.
---
...Я работаю антинаучным аферистом...

shlyumper

Определи функциональность.

Ivan8209

В противоположность "императивнее".
---
"Расширь своё сознание!"

shlyumper

Я трактовал в значении "В противополжность ``ни на что не годится''".

bleyman

Тогда lambda calculus ещё "функциональнее". В нём не то что императивно, в нём вообще почти как угодно писать тяжело.

yulya

valgrind точно поможет

margadon

кстати, в приведенном примере программа бы вылетела уже на последней стадии цикла, т.к. q[n] - незааллоченное место (там n элементов, значит максимальный индекс n-1 правильно?
это логично, но, кажется, неверно (хотя я в линухе не проверял)
при выделении подобных массивов вроде как по стандарту выделяется место и под следующий за последним элемент (при этом он чаще всего ноль и вроде как я об этом у Страуструпа читал когда-то... если это не так, поправьте

margadon

посмотри какой у него тип у Q - имхо, судя по строкам его программы, он правильно удаляет то, что создал

Ivan8209

> при выделении подобных массивов вроде как по стандарту
Ключевое слово --- "вроде".
Ссылку на стандарт приведёшь?
> выделяется место и под следующий за последним элемент
> (при этом он чаще всего ноль
> и вроде как я об этом у Страуструпа читал когда-то...
А причём здесь Страуструп?
---
<<...Должны мыслить существительными и глаголами:
"он встретился", "она сказала", "он передал"...
Вы что, не допускаете мысли?..>>

margadon

ты мне будешь указывать где у меня ключевые слова? тебе нравится игра "найди Х" (прямо из анекдота)?
я считаю всё написанное в книжке страуструпа стандартом или как минимум тем, чему стоит доверять
ты лучше скажи как линукс реагирует на обращение за последний элемент массива

Ivan8209

> я считаю всё написанное в книжке страуструпа стандартом
> или как минимум тем, чему стоит доверять
Название книжки скажи, да?
> ты лучше скажи как линукс реагирует на обращение за последний
> элемент массива
Меня это не волнует.
---
...Я работаю антинаучным аферистом...

margadon

Язык программирования C++. Ed. 3
и вообще, зачем ты меня коментишь, если по существу ничего сказать не можешь и на мои вопросы не отвечаешь? попиздеть-то и я люблю, но зачем это делать тут?

Ivan8209

> Язык программирования C++. Ed. 3
А теперь прочитай заголовок.
---
"Vyroba umelych lidi, slecno, je tovarni tajemstvi."

Dasar

при выделении подобных массивов вроде как по стандарту выделяется место и под следующий за последним элемент (при этом он чаще всего ноль
не помню такого.
да, и на страуструппа это не похоже, он обычно как раз как можно меньше старался вдаваться в детали реализации.

velet25

пример:
.................
int i;
double** Q;
Q=(double**) malloc(5*sizeof(double*;
for (i=0; i<5; i++)
Q[i]=(double*) malloc(4*sizeof(double;
.................
free(Q[1]); - тут вылетает ошибка! почему?
Пипец, только что нашел ошибку - я внутренний массив аллочил
Q[i]=(double*) malloc(4*sizeof(double*
Ну надо же... Как только прога работала? Ведь ятуда записывал! У double* и double что, размеры совпадают?..

margadon

ну вообще на моей 32битной машинке - нет, double - 8байт, double* - 4

Ivan8209

> У double* и double что, размеры совпадают?..
Вообще-то, что-что, а такое легко проверить.
---
...Я работаю антинаучным аферистом...

Maurog

код надо было правильно копировать (причем полностью, а не кусками).
тогда бы без флуда тебе указали на ошибку.

Olyalyau

По вопросу: используй malloc debugger (например, valgrind).
[offtopic]

int i;
double** Q;
Q=(double**) malloc(5*sizeof(double*;
for (i=0; i<5; i++)
Q[i]=(double*) malloc(4*sizeof(double;
.................
free(Q[1]);

Раз у тебя строки одной (или приблизительно одной) длины, делай так:

int i;
double* Q;
Q=(double*) malloc(5*4*sizeof(double;
.................
free(Q);

А для обращения к элементам используй Q[N(i,j)] вместо Q[i][j], где N(i,j) — функция (макрос) возвращающая либо i+j*5, либо j+i*4 (в зависимости от того, какой индекс у тебя меняется подряд — этот индекс лучше ставить без умножения). Тогда программа у тебя будет проще и ошибок в ней будет меньше, а работать она будет быстрее. А если твоя замечательная функция N(i,j) в режиме отладки ещё и проверять диапазоны будет (или хотя бы тривиальное (i+j*5)%20 делать то ошибку тебе станет найти проще, так как из класса "undefined behaviour" ты её, скорее всего, выведешь.
[/offtopic]
Оставить комментарий
Имя или ник:
Комментарий: