Проблема с простым указателем C - PullRequest
3 голосов
/ 29 сентября 2011

Прошло много (много ...) времени с тех пор, как я занимался программированием на С, и я застрял в том, что должно быть действительно простой проблемой.У меня есть простая функция, которая вызывает другую функцию, которая выделяет некоторую память в куче, заполняет ее структурой и возвращает указатель обратно.Все выглядит отлично, за исключением случаев, когда указатель возвращается к вызывающей функции, его адрес поврежден.

Вот соответствующий код:

Вызываемая функция:

struct server_type *init_gwserver(Cfg* cfg)
{
    struct server_type *res = NULL;
    // Lots of irrelevant code removed here - doesn't reference res.

    res = gw_malloc(sizeof(struct server_type));
    gw_assert(res != NULL);

    res->server_start = gwserver_start; // Pointer to a function
    res->server_stop = gwserver_stop; // Pointer to another function
    return res;
}

Вызовфункция:

struct server_type *do_init_server(Cfg *cfg)
{
    struct server_type *res = NULL;
    res = (struct server_type *)init_gwserver(cfg);
    if (res) {
        return res;
    }
}

ОК, вот странность.Когда «res» возвращается вызывающей функции, адрес, на который указывает указатель, изменяется и становится недействительной ссылкой на память.Вот быстрый пример с GDB.Комментарии (// ...) мои ...

Breakpoint 1, init_gwserver (cfg=0x100214e30) at init_gwserver.c:339
339 res->server_stop = gwserver_stop;
(gdb) print /x res
$18 = 0x100215b10
// Pointer above looks fine and seems to be a valid address
(gdb) p *res
$14 = {
    type = 0x100215460, 
    sql_enter = 0x100003820 <gwserver_start>, 
    sql_leave = 0x100005ae0 <gwserver_stop>, 
}
// Contents of the pointer are looking great
(gdb) next
340  return res;
(gdb) print /x res
$19 = 0x100215b10
// Pointer is unchanged - should return this value just fine.
(gdb) next
do_init_server (cfg=0x100214e30) at init_server.c:52
52 if (res) {
(gdb) print /x res
$20 = 0x215b10
// WOW - what the hell happened to the address pointed to by res? It lost the leading 100.
(gdb) p *res
Cannot access memory at address 0x215b10
// Yep, it's definitely now an invalid pointer. Crash time...`

Вероятно, это что-то действительно, очень простое, но я не могу это понять.Кто-нибудь получил предложения?

Спасибо!Тоби.

1 Ответ

5 голосов
/ 29 сентября 2011

Этот акт выглядит подозрительно: (struct server_type *)init_gwserver(cfg).

Если приведение необходимо для компиляции кода, это указывает на то, что на сайте вызова не отображается правильный прототип для init_gwserver.

Если прототипа не видно, компилятор сделает предположение, что функция возвращает int. Когда возвращаемое значение извлекается как нечто, чем оно не является, в зависимости от реализации, его значение может быть повреждено, а при преобразовании обратно в указатель информация может быть безвозвратно потеряна.

Приведение не должно быть необходимым, и если его удаление вызывает ошибку компиляции, это указывает на то, что вам нужно добавить (или #include) правильный прототип для init_gwserver до точки, где вы пытаетесь вызвать его.

...