Почему вылетает?

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

Ответить
И.Владимир
Сообщения: 7
Зарегистрирован: 27 окт 2007, 18:58

28 ноя 2007, 10:03

Здравствуйте!
Пожалуйста, скажите где ошибка.
После запуска EXE - "вылетает", см. код ниже.
Компилятор - VC6, ОС - XP.

//
// Problem.c
//

#include <stdio.h>
#include <stdlib.h>

typedef struct
{ unsigned char* text;
unsigned long int len;//Количество символов в text, включая символ окончиня строки - '\0';
} strtext_t;

typedef struct
{ strtext_t *s;
} table_string_t; // Строка таблицы (строка ячеек).

typedef struct
{ unsigned char nc; // Количество колонок в таблице.
unsigned long int ns; // Количество строк в таблице.
table_string_t *sl; // Список табличных строк (кол-во = ns).
table_string_t c_name; // Строка таблицы. Названия колонок (кол-во = nc).
} table_t;

table_t tt;

int main()

{
char i;

tt.sl = NULL;
tt.c_name.s = NULL;
tt.nc = 0;
tt.ns = 0;

/* ХАРАКТЕР ПРОБЛЕМЫ
Если выделять память при помощи malloc - все нормально.
Если выделять и _изменять_ при помощи realloc и при этом еще что-то
записывать в tt.c_name.s[х].x - то происходит "вылет".
Если запись в tt.c_name.s[х].x производить как ниже, то вылетает на 6
"проходе" цикла, а если записывать более активно (выделять для .text память
и туда писать) - то вылетает уже на 3-ем проходе. */

for (i=0; i<8; i++)
{
tt.c_name.s = (table_string_t*) realloc (tt.c_name.s, sizeof (table_string_t) * i+1);
tt.c_name.s.text = NULL;
}

return 0;
}
BBB
Сообщения: 1272
Зарегистрирован: 27 дек 2005, 13:37

28 ноя 2007, 10:23

А почему бы не выделять при помощи new? Так сказать, в "красивом стиле" C++?
Не знаю, решит ли это проблему, но, вроде,ри разработке C++ приложений рекомендуют этими функциями пользоваться.
И.Владимир
Сообщения: 7
Зарегистрирован: 27 окт 2007, 18:58

28 ноя 2007, 10:45

BBB писал(а):А почему бы не выделять при помощи new? Так сказать, в "красивом стиле" C++?
Не знаю, решит ли это проблему, но, вроде,ри разработке C++ приложений рекомендуют этими функциями пользоваться.
На Си вся программа и то, что она использует (.c и .h файлы для работы со строками, файлами и пр.). К стыду своему пишу на Си (уже долго), однако приходит осознанование того, что в Си не хватает некоторых возможностей, а в последнее время точно понял: надо С++. Недавно стал Си++ осваивать, а пока пишу на Си пользуясь старыми наработками (времени нехватает для С++ практики).
Аватара пользователя
Romeo
Сообщения: 3091
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

29 ноя 2007, 11:27

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

tt.c_name.s = (table_string_t*) realloc (tt.c_name.s, sizeof (table_string_t) * i+1);
tt.c_name.s[i].text = NULL;
Первый вопрос. Что ты хочешь добиться таким кодом? Зачем в цикле делать realloc, если можно один раз до цикла сделать malloc?

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

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

sizeof (table_string_t) * i+1
Как ты думаешь в каком порядке будет выполняться операции в этом выражении? Подсказка: операция умножить имеет более высокий приоритет.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
И.Владимир
Сообщения: 7
Зарегистрирован: 27 окт 2007, 18:58

29 ноя 2007, 12:18

Romeo писал(а): Первый вопрос. Что ты хочешь добиться таким кодом? Зачем в цикле делать realloc, если можно один раз до цикла сделать malloc?
Прости, перед постом кода на форум я его изменил и урезал настолько, чтобы всякий мог у себя его откомпилировать. Для строки таблицы выделяеться память в N строк (ячеек), где N - количество колонок. У меня их 8, но может быть сколько угодно, поэтому память выделяю не сразу а по мере надобности (да и не хочется сразу, ведь должен же realloc работать, он у меня всегда работал).
Romeo писал(а): Внимательно изучи этот фрагмент:
sizeof (table_string_t) * i+1
Ты прав, нужны скобки (это я перед постом ошибку допустил). Но и со скобками проблема остается. Чую, что где-то глупая ошибка, так бывает часто, но вот где... Эх!
Аватара пользователя
Romeo
Сообщения: 3091
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

29 ноя 2007, 13:03

Попробуй realloc заменить на malloc, memcpy, free. Если поможет, то бока в твоём коде. Если не поможет, то кривой компилер :) У меня других предложений пока нет.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Аватара пользователя
WinMain
Сообщения: 913
Зарегистрирован: 14 янв 2005, 10:30
Откуда: Москва
Контактная информация:

29 ноя 2007, 16:22

Ошибка многих начинающих программистов состоит в том, что они сразу начинают писать программный код, не продумав до конца архитектуру приложения. Из-за этого потом трудно бывает разобраться в их коде и найти в нём ошибку. Даже если ты выполняешь задачу не на С++, а на обычном Си, то всё равно тебе сначала нужно подумать, из каких сущностей будет состоять твоя программа и придумать целый набор функций для работы с ними. Ну например, если тебе нужно реализовать таблицу, то тебе понадобятся примерно такие функции:
CreateTable(), DestroyTable(),
InsertColumn(), DeleteColumn(),
AddRow(), DeleteRow(),
CreateCell(), DestroyCell(),
GetCellValue(), SetCellValue(), и др.

В этих функциях ты должен будешь использовать функции выделения/освобождения памяти, инициализацию массивов, и т.д. А уже в функции main() ты должен использовать свои функциональные заготовки. А если ты в одной функции main() непосредственно будешь писать циклы по выделению и освобождению памяти, то ты только запутаешь себя и других. Ничего хорошего из этого не получится.
И.Владимир
Сообщения: 7
Зарегистрирован: 27 окт 2007, 18:58

29 ноя 2007, 17:23

WinMain писал(а):Ошибка многих начинающих программистов состоит в том, что они сразу начинают писать программный код, не продумав до конца архитектуру приложения. Из-за этого потом трудно бывает разобраться в их коде и найти в нём
Код в мойм вопросе лишь для того, чтобы продемонстрировать проблему. Вытащил из порядочного места, вставил в main() и он оставил свою проблемоспособность.
И.Владимир
Сообщения: 7
Зарегистрирован: 27 окт 2007, 18:58

29 ноя 2007, 18:07

Ошибка найдена. Тип должен быть (strtext_t *), а не (table_string_t*). Это не я нашел, а хороший человек на форуме ином.
Ответить