2013-11-28 6 views
-1

Я просмотрел весь Google и не могу понять, почему malloc не работает в моем коде. Я включил части кода, которые, как мне кажется, полезны для понимания проблемы.Malloc ломается, когда он не должен

Странная часть состоит в том, что я использовал malloc 5 строк выше точно таким же образом, и каждый раз для каждого из них успешно выполняется, но последовательно выходит за второй. Поскольку я прошел через gdb, указатель для parent-> left_tree равен 0x0, прежде чем он будет изменен malloc-ed, и он отлично работает, а затем, когда дело доходит до parent-> right_tree, он терпит неудачу каждый раз с данным загадочным сообщением об ошибке , Я пробовал экспериментировать с разными значениями внутри malloc, такими как malloc (64) и malloc (10000), и результаты идентичны.

Вот функция кода, где таНос терпит неудачу:

int 
prefix_input(expr_tree_T parent) 
{ 

    char *token = get_next_token(); 
    int int_value; 
    double dub_value; 
    int type = node_type(token); 

    if (type == -1) 
    { 
     fprintf(stderr, "ERROR: '%s' is invalid input.\n", token); 
     exit(2); 
    } 

    parent->type = type; 

    if (type == OPERATOR) 
    { 
     parent->value.operator = token[0]; 
     parent->left_subtree = malloc(sizeof(expr_tree_T)); 
     mem_check(parent->left_subtree, "left subtree"); 

     prefix_input(parent->left_subtree); 

     parent->right_subtree = malloc(sizeof(expr_tree_T)); //<-- ***Right here*** 
     mem_check(parent->right_subtree, "right subtree"); 

     prefix_input(parent->right_subtree); 
    } 
    else if (type == INTEGER) 
    { 
     sscanf(token, "%d", &int_value); 
     parent->value.int_value = int_value; 
     parent->left_subtree = NULL; 
     parent->right_subtree = NULL; 
    } 
    else if (type == DOUBLE) 
    { 
     sscanf(token, "%lf", &dub_value); 
     parent->value.double_value = dub_value; 
     parent->left_subtree = NULL; 
     parent->right_subtree = NULL; 
    } 

    return 0; 
} 

Вот код для структуры, которая оказывает память выделяется:

typedef struct expr_tree_node 
{ 

    struct expr_tree_node *left_subtree; 
    struct expr_tree_node *right_subtree; 

    int type; 

    union 
    {   
     char operator; 
     int int_value; 
     double double_value; 
    } value; 

} * expr_tree_T; 

Это все мой включен заголовок файлы:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 

Это как компилируется код:

gcc -Wall -std=c99 -D_POSIX_SOURCE A12P2.c -o a12p2 -g 

Это образец отладки с помощью GDB. Я могу заметить, что указатель для parent-> right_subtree равен 0, который, как я исследовал, является самым безопасным для использования malloc вообще.

prefix_input (parent=0x804c008) at A12P2.c:171 
171   parent->right_subtree = malloc(sizeof(expr_tree_T)); 
(gdb) print parent->left_subtree 
$7 = (struct expr_tree_node *) 0x804c160 
(gdb) print parent->right_subtree 
$8 = (struct expr_tree_node *) 0x0 
(gdb) s 
a12p2: malloc.c:2369: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)- 
>bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size 
== 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct 
malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 
1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed. 

Program received signal SIGABRT, Aborted. 
0xb7fdd424 in __kernel_vsyscall() 
+1

Что-то в вашей программе разлагает кучу. Используйте valgrind, чтобы помочь найти его. – Barmar

+0

Как вы называете 'prefix_input()'? –

ответ

1

Этот тип ошибки указывает на то, что ваше приложение испорчены структуры данных, используемые malloc(). Обычно это происходит из-за того, что вы пишете вне выделенного блока памяти или записываете в память, которая была освобождена.

В этом случае, кажется, что вы не выделять достаточно памяти для структур:

parent->left_subtree = malloc(sizeof(expr_tree_T)); 

Учитывая прототип этой функции, она выглядит, как будто expr_tree_T является ЬурейеЕ для указателя на структуру , а не сама структура. Если это действительно так, то sizeof(expr_tree_T) заканчивается размером этого указателя, а не структуры, поэтому вы выделяете гораздо меньше памяти, чем это действительно необходимо!

Я настоятельно рекомендую вам изменить определение этого типа, чтобы сделать его именем для структуры (поэтому теперь функция примет expr_tree_T * в качестве аргумента). Если вы обнаружите, что звезды неприятны, напечатайте указатель на что-то вроде expr_tree_ref и используйте это в случае необходимости. В файле заголовка, это может выглядеть примерно так:

typedef struct expr_tree { 
    .... 
} expr_tree_T, *expr_tree_ref; 

В противном случае, вам нужно будет конкретно ссылаться на структуру в вашем выражении sizeof():

malloc(sizeof(struct what_an_expr_tree_T_points_to)) 

который (даже когда вы используете реальные имя, что бы это ни было) намного грязнее, чем sizeof(expr_tree_T).

+0

Спасибо большое, я изменил это и реструктурировал некоторые части программы, и он отлично работает. Наверное, мне просто нужно освежить мое понимание указателей и тому подобное. Когда вы сказали в начале, что мое приложение, вероятно, повреждено структурами данных, используемыми malloc(), что вы имеете в виду? Вы предлагаете, чтобы моя программа только что имела доступ к некоторой памяти, которую malloc пытался использовать для своих целей? Было ли это случайно, и может ли программа случайно получить доступ к памяти из других программ, работающих внутри моей? –

+0

Распределитель памяти хранит данные «бухгалтерии» в окружающих его блоках памяти. Запись за пределы выделенного блока или до начала может испортить эти данные. Системная память защищает вас от доступа к памяти из других программ, хотя - самое худшее, что вы обычно можете сделать, это испортить себя. – duskwuff

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