Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Область видимости и время жизни


Автор: konshyn 2.10.2014, 21:46
Сначала код. Потом вопрос, который не могу решить. Он в пару строк:)

файл A.h
Код

#ifndef __A_H__
#define __A_H__

struct A;

struct A *a_init(int cnt);
int use(struct A *a);

#endif /* __A_H__ */



Файл А.с
Код

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

struct A {
    int a[10];
    int *b;
    int c;
    int cnt;
};

static struct A *_a;

struct A *a_init(int cnt) {
    _a = calloc(cnt, sizeof(struct A));
    int i;
    for (i = 0; i < cnt; i++)
        _a[i].b = calloc(cnt*cnt, sizeof(int));

    for (i = 0; i < cnt; i++) {
        _a[i].c = i*i*i;
        _a[i].cnt = cnt;
        int j;
        for (j = 0; j < cnt * cnt; i++)
            _a[i].b[j] = j * 3; 
    }
    return _a;
}

int use(struct A *a) {
    int i;
    int cnt = a[0].cnt;
    for (i = 0; i < cnt; i++) {
        printf("%d \n", a[i].c);
        int j;
        for (j = 0; j < cnt * cnt; i++) 
            printf("%d ", a[i].b[j]);
        printf("\n\n\n");
    }
}


Файл main.c
Код

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

int main()
{
    const int cnt = 10;
    struct A *a = a_init(cnt);
    use(a);
    return 0;
}


Я хочу сделать в стиле сишных библиотек свою. Есть функция, которая инициализирует структуру и возвращает на нее указатель. А потом передавать этот указатель в другие функции, которые будут что-то делать, скрывая свои действия от пользователя, и возвращать результат. как это происходит в libnet, mysql-client и т.п.

В коде, что выше, я показал пример. Но в функции use() происходи segmentation fault. 
Не могу разобраться. помогите, плиз

Автор: baldina 2.10.2014, 23:38
оно до use доходит? <line 24>
Цитата(konshyn @  2.10.2014,  21:46 Найти цитируемый пост)
 for (j = 0; j < cnt * cnt; i++)


но если и доходит, то <line 36>
Цитата(konshyn @  2.10.2014,  21:46 Найти цитируемый пост)
 for (j = 0; j < cnt * cnt; i++) 


а в остальном, прекрасная маркиза, http://ideone.com/Ofl1Sb

Автор: konshyn 3.10.2014, 12:57
Цитата(baldina @  2.10.2014,  23:38 Найти цитируемый пост)
а в остальном, прекрасная маркиза, все хорошо, все хорошо 

Сначала нашел ошибку, а потом только открыл Ваш код:)
А вообще, забавное совпадение с ошибкой, хотя причины разные.

этот код всего лишь миниатюрная версия того, что я написал и где сделал ошибку. и здесь тоже - по невнимательности.

в своей библиотеке тоже нашел ошибку.
мини-код:

Код

int push_in_new_cell(struct A *new_cell) {
    new_cell = get_new_cell();  // возвращает адрес свободной ячейки
    new_cell->.....
    //тут заполнение новой ячейки
    return 0;
}

int push() {
    struct A *cell = NULL;
    push_in_new_cell(cell);
    cell->....  // тут и происходил segmentation fault
}


думаю, что знающие поняли ошибку.
а незнающие, если интересно, пусть подумают.
если никто не объяснит в комментариях ошибку, то позже разъясню.

Автор: baldman88 3.10.2014, 14:12
И, если не секрет, где здесь ошибка?
Если функция get_new_cell возвращает нормальный указатель (а вдруг она вернет NULL), то, по идее, все должно работать. В противном случае сегфолт будет в функции push_in_new_cell.
При работе с указателями лучше всегда проверять их на валидность перед использованием.

Автор: konshyn 3.10.2014, 16:43
Цитата(baldman88 @  3.10.2014,  14:12 Найти цитируемый пост)
Если функция get_new_cell возвращает нормальный указатель (а вдруг она вернет NULL),

get_new_cell всегда возвращает валидный указатель. 

все дело в передаче указателя cell из функции push() в функци. push_in_new_cell()

Добавлено через 1 минуту и 10 секунд
P.S. Если бы функция get_new_cell возвращала когда-либо невалидный указатель, то в сообщение я бы включил и ее код.

Автор: baldina 4.10.2014, 23:30
baldman88, параметры передаются по значению

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)