nixp.ru v3.0

22 октября 2017,
воскресенье,
11:17:25 MSK

DevOps с компанией «Флант»
Fatal написал 30 октября 2004 года в 20:45 (767 просмотров) Ведет себя как мужчина; открыл 123 темы в форуме, оставил 484 комментария на сайте.

#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»);

}

vnp

Стало быть, сколько здесь места выделяется?



char***p=(char***)malloc(lin);

Правильно, lin байтов. А сколько используется?



while(i
  p[i]=malloc(col);
  printf("%x\n",p[i]);
  ++i;
}

Тоже правильно, lin * sizeof(char **) байтов.

Fatal
vnp
Стало быть, сколько здесь места выделяется?

Правильно, lin байтов. А сколько используется?

Тоже правильно, lin * sizeof(char **) байтов.

Конечно!!! Ура!!!!!!

Спасибо!

Fatal

Вот что заничит перейти с Си++ на Си.

char***p=new char**[lin]