2015-08-07 3 views
0

У меня есть ошибка, в которой неправильное значение передается в качестве аргумента функции в программе на C. Как он работает, я объявляю статический указатель на структуру данных типа typedef-ed как глобальную переменную. Существует функция инициализации, в которой эта переменная инициализируется. Эта функция выделяет память, инициализирует поля данных и возвращает указатель. Что-то вроде этого:неверное значение указателя, переданное функции C

static my_type *my_ptr; 
... 
void init(void){ 
    my_ptr = init_my_type(); 
} 

Функция init_my_type довольно прямо вперед:

void *init_my_type(void){ 
    my_type *x = malloc(sizeof(my_type); 
    x->arg1 = 0; 
    ... // more field initializations 
    return x; 
} 

Позже я использую my_ptr в качестве аргумента другой функции:

void do_stuff(void){ 
    func(my_ptr); 
} 

Проблема у меня есть что я обнаружил ошибку в кишках func, когда некоторые данные в структуре данных, которые my_ptr указывают на ac cessed.

Когда я запускаю отладчик я получаю симпатичную шестнадцатеричное значение, когда я разбиваю на init_my_type:

(gdb) finish 
Value returned is $26 (void *) 0x79b6c0 

Позже, в функции do_stuff, my_ptr имеет то же шестнадцатеричное значение:

(gdb) print my_ptr 
$26 = (my_type *) 0x79b6c0 

но, когда я ломаю func, аргумент, который он получает, имеет совершенно другое значение.

Breakpoint 2, func(arg=0x1388) 

Я типа-каламбурная указатели повсюду, но я не вижу, что это должно изменить адрес в памяти, что они указывают на, не так ли? Кроме того, функция func объявлена ​​inline, но почему это должно повлиять на это? Все это кажется мне правильным - вполне возможно, что я делаю что-то глупое, чего я не вижу.

Вот полная программа упрощенного кода. В действительности все эти функции не вызываются главным образом, а динамически загружаются вспомогательные функции. Тем не менее, я не вижу, как адрес, на который указывает my_ptr, должен измениться при передаче на func.

#include "stdlib.h" 
#include "stdio.h" 

typedef struct _type{ 
    int *i1; 
    float *f1; 
}my_type; 

static my_type *my_ptr; 

void *init_my_type(void){ 

    my_type *x = malloc(sizeof(my_type)); 
    x->f1 = malloc(sizeof(float)); 
    x->i1 = malloc(sizeof(int)); 
    x->f1[0] = 123.456; 
    x->i1[0] = 789; 

    return x; 

} 

void init(void){ 

    my_ptr = init_my_type(); 

} 

inline void func(void *arg){ 

    my_type *x = (my_type *)arg; 
    printf("%d %f\n", *x->i1, *x->f1); 

} 

void do_stuff(void){ 

    func(my_ptr); 

} 


int main(void){ 

    init(); 
    do_stuff(); 


} 
+3

Просьба указать [минимальный, завершающий, проверяемый пример] (http://stackoverflow.com/help/mcve) проблемы, с которой вы столкнулись. Невозможно рассказать, что происходит на основе того, какой маленький код здесь до сих пор. – dbush

+0

Не могли бы вы рассказать мне, что не ясно? Я включил все детали в кратчайшие возможные мысли. Затем я выполняю свой отладочный процесс точно так, как он появляется. Для меня это совершенно ясно, но я написал код и думаю об этом весь день. Пожалуйста, дайте мне больше информации. – dmedine

+0

Не могли бы вы выслать код своей функции 'init_my_type()'? Segfaults часто вызваны разыменованием неинициализированных указателей – bpgeck

ответ

0

Следующие не причина проблемы (и не может, так как статические Глобал инициализируются к нулю по умолчанию). Хотя основная идея по-прежнему актуальна: действительно ли прошедший указатель действительно тот, который был инициализирован.


Грубое предположение:

static my_type *my_ptr; 

Может быть, что эта линия является частью какого-либо файла заголовка? Потому что тогда у вас есть глобальный my_ptr в каждом исходном файле, который включает этот заголовок.

Поскольку вы написали, что это очень большой проект, я предполагаю, что вы разделили код и поместили его в несколько исходных файлов. Предполагая, что функция init находится в другом исходном файле, чем функция use, это означает, что они обращаются к различным указателям. В то время как один init имеет дело с инициализацией, используется один func, неинициализированный.

Чтобы проверить это, вы должны напечатать адрес глобальной переменной указателя (&my_ptr) в обеих функциях.

+0

Хммм. 'my_ptr' объявляется в том же файле, который вызывает' func'. 'init_my_func' находится в другом файле, но' init' - нет. Согласно моему (ограниченному) пониманию, поскольку 'my_ptr' объявлен в том же файле, что и' init', тогда значение, возвращаемое 'init_my_func' (вызываемое' init'), в порядке. – dmedine

+0

Хорошо, тогда я догадался, что не так. Но все же, можете ли вы напечатать (от фактического кода, а не отладчика) адрес указателя как при инициализации, так и при использовании? –

+1

Если значение, которое func() было равно нулю, статическая вещь имела бы смысл, поскольку C определяет, что статические переменные автоматически инициализируются до нуля до их ссылки. Однако это было не так. –

Смежные вопросы