#include
#include
#include /*scandir(), alphasort()*/
void free_dirs(struct dirent***pd, int n);
void print_dirs(struct dirent**pd, int n);
char***db_alloc(size_t lin,size_t col);
void db_free(char***p,size_t lin);
/*
Почему во FreeBSD выводятся сообщения, что адреса уже освобождены (когда освобождаю arr_progs),
а в Linux выводится ошибка сегментации?
Причем если функцию scandir() убрать все будет в порядке? Может это баг?
Внизу кусок программы, в котором локализована ошибка. Этот кусок выделяет память для массива указателей на указатели указателей.
В программе массив должен хранить указатели на строки, приблизительно так
char***arr_progs;
char*str_pointer;
arr_progs[0][0]=str_pointer;
Поэтому память под третий уровень не выделяется.
Дело конечно не в этом, а в следующим:
цепь действий, которые выполняются в данном куске программы:
1. выделяется память для arr_progs
2. строится массив для списков файлов текущей директории с помощью scandir()
3. распечатывается список файлов
4. освобождается массив arr_progs (регирует на NULL)
5. освобождается список файлов в текущей директории (реагирует на NULL)
Так вот, если убрать второй пункт, то в четвертом пункте не будет вылезать ошибка.
А нужно, что бы второй пункт обязательно был.
В приведенном куске, существует функция print_addresses(), которя распечатывает адреса массива arr_progs
, где i меняется от 0 до max_prog.
Если запустить эту прогу под FreeBSD, то адреса, которые содержит arr_progs до вызова функции scandir() будут отличаться от тех
, которые будут распечатаны после вызова scandir, плюс ко всему будут предупреждения при освобождении массива arr_progs
, что эта память уже освобождена (маленькое отступление: что мне и нравиться во FreeBSD)
В Linux они отличаться не будут, но в конце будет выведена ошибка сегментации.
Все результаты, о которых написано здесь могут отличаться на других машинах, но думаю, что на всех будет видна ошибка.
Почему scandir так влияет на arr_progs.
Заранее приношу свои извенения, если ошибка глупая, я уже сижу который час за компом и перестал соображать и глазки покраснели.
*/
void print_addresses(char***p,int num){
int i=0;
puts(«\nstart»);
while(i
printf(«%x\n»,p);
++i;
}
puts(«end»);
}
const size_t max_prog=10,max_arg=20;
int main(void){
int quant_files=0;/*files quantity to return scandir()*/
char***arr_progs;
struct dirent**pdirs=NULL;
/* выделение памяти массива указателей на указатели указателей, причем память под третий уровень не выделяется */
arr_progs=db_alloc(max_prog,max_arg);
/* распечатка дипазона адресов с arr_progs[0] до arr_progs[max_prog-1] включительно */
print_addresses(arr_progs,max_prog);
/* если эту функцию закоментировать ошибки не будет */
/*???????*/quant_files=scandir(«.», &pdirs,NULL,alphasort);
/* распечатка имен файлов, которая вернула scandir() */
print_dirs(pdirs,quant_files);
/* распечатка дипазона адресов с arr_progs[0] до arr_progs[max_prog-1] включительно */
print_addresses(arr_progs,max_prog);
/* освобождение памяти, реализована реакция на нулевой указатель */
db_free(arr_progs,max_prog);
free_dirs(&pdirs,quant_files);
return 0;
}
/* определение функций*/
void free_dirs(struct dirent***pd, int n){
if(!pd || !*pd || !n){
puts(«free_dirs: pointer == NULL, return»);
return;
}
puts(«\nenter into free_dirs»);
while(n--)
if((*pd)[n]){
free((*pd)[n]);
(*pd)[n]=NULL;
}
else{
puts(«pd == NULL»);
}
free(*pd);
*pd=NULL;
puts(«\nexit from free_dirs»);
}
void print_dirs(struct dirent**pd, int n){
int i=0;
if(!pd)
return;
while(i
if(pd && pd->d_name)
puts(pd->d_name);
else
puts(«print_dirs NULL»);
++i;
}
}
char***db_alloc(size_t lin,size_t col){
size_t i=0;
char***p=(char***)malloc(lin);
puts(«\nenter into db_alloc»);
if(!p)return NULL;
while(i
p=malloc(col);
printf(«%x\n»,p);
++i;
}
printf(«\nexit from db_alloc: col = %d»,i);
return p;
}
void db_free(char***p,size_t lin){
puts(«\nenter into db_free»);
print_addresses(p,lin);
while(lin--)
free(p[lin]);
free(p);
puts(«\nexit from db_free»);
}
Последние комментарии
- OlegL, 17 декабря 2023 года в 15:00 → Перекличка 21
- REDkiy, 8 июня 2023 года в 9:09 → Как «замокать» файл для юниттеста в Python? 2
- fhunter, 29 ноября 2022 года в 2:09 → Проблема с NO_PUBKEY: как получить GPG-ключ и добавить его в базу apt? 6
- Иванн, 9 апреля 2022 года в 8:31 → Ассоциация РАСПО провела первое учредительное собрание 1
- Kiri11.ADV1, 7 марта 2021 года в 12:01 → Логи catalina.out в TomCat 9 в формате JSON 1
Стало быть, сколько здесь места выделяется?
Правильно, lin байтов. А сколько используется?
Тоже правильно, lin * sizeof(char **) байтов.
Конечно!!! Ура!!!!!!
Спасибо!
Вот что заничит перейти с Си++ на Си.
char***p=new char**[lin]