2017-02-09 5 views
-1

Я только начал кодирование и задал начальный вопрос. Поэтому у меня есть двоичное дерево. После того, как я добавлю первый узел к нему, я бы хотел найти дерево, если есть дублированный узел с тем же значением. Но я получаю ошибку, когда я пытаюсь искать дерево, которое имеет только один узел: Вот мой узел:C переполнение буфера переполнения программирования

struct node{ 
int data; 
struct node* left; 
struct node* right;}; 

Вот функция, которую я использовал для создания первого узла

struct node* createnode(int num){ 
struct node *p=malloc(sizeof(struct node*)); 
p->data=num; 
return p; 
} 

И я добавил, как это:

struct node *root; 
root=createnode(b); 

Вот функция поиска

char * search(int num, struct node *p, int dep){ 
dep=1; 
char *result="n"; 
if(p==NULL){result="n";return result;} 
struct node * root; 
root=p; 
while(root!=NULL){ 
if(num==root->data){ 
result= "y";break; 
} 
if(num>root->data && root->right!=NULL){ 
root=root->right;dep++; 
} 
if(num<root->data&&root->left!=NULL){ 
root=root->left;dep++; 
} 
if(num >root->data&&root->right==NULL){ 
result= "n";break; 
} 
if(num <root->data&&root->left==NULL){ 
result="n";break; 
} 
} 
return result; 
     } 

Здесь ошибка я получил

==6841== ERROR: AddressSanitizer: heap-buffer-overflow on address  0x60040000e000 at pc 0x400eb5 bp 0x7fff3d5302c0 sp 0x7fff3d5302b0 
READ of size 8 at 0x60040000e000 thread T0 
#0 0x400eb4 (/.autofs/ilab/ilab_users/xy139/night+0x400eb4) 
#1 0x402911 (/.autofs/ilab/ilab_users/xy139/night+0x402911) 
#2 0x7f2196abdb14 (/usr/lib64/libc-2.17.so+0x21b14) 
#3 0x400a78 (/.autofs/ilab/ilab_users/xy139/night+0x400a78) 
0x60040000e000 is located 8 bytes to the right of 8-byte region [0x60040000dff0,0x60040000dff8) 
allocated by thread T0 here: 
#0 0x7f2196e74129 (/usr/lib64/libasan.so.0.0.0+0x16129) 
#1 0x402071 (/.autofs/ilab/ilab_users/xy139/night+0x402071) 
#2 0x402899 (/.autofs/ilab/ilab_users/xy139/night+0x402899) 
#3 0x7f2196abdb14 (/usr/lib64/libc-2.17.so+0x21b14) 
Shadow bytes around the buggy address: 
0x0c00ffff9bb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
0x0c00ffff9bc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
0x0c00ffff9bd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
0x0c00ffff9be0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
0x0c00ffff9bf0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa 00 fa 
=>0x0c00ffff9c00:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
0x0c00ffff9c10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
0x0c00ffff9c20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
0x0c00ffff9c30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
0x0c00ffff9c40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
0x0c00ffff9c50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
Shadow byte legend (one shadow byte represents 8 application bytes): 
Addressable:   00 
Partially addressable: 01 02 03 04 05 06 07 
Heap left redzone:  fa 
Heap righ redzone:  fb 
Freed Heap region:  fd 
Stack left redzone: f1 
Stack mid redzone:  f2 
Stack right redzone: f3 
Stack partial redzone: f4 
Stack after return: f5 
Stack use after scope: f8 
Global redzone:  f9 
Global init order:  f6 
Poisoned by user:  f7 
ASan internal:   fe 
==6841== ABORTING 

Я благодарю всех, кто готов помочь !!!!

+0

Не забудьте установить два указателя на нуль в функции создания узла. –

+2

Пожалуйста, открепите свой код. –

ответ

2
struct node *p = malloc(sizeof(struct node*)); 

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

struct node *p = malloc(sizeof(struct node)); 

Это легче запомнить, чтобы сделать это, если вы разыменовываетесь целевой указатель и передать его размер, чтобы malloc в качестве аргумента, как так:

struct node *p = malloc(sizeof(*p)); 

Если вы должны были изменить тип данных из p в более поздней версии программы, тогда вам не потребуется обновлять соответствующие аргументы до malloc.

+1

OMG спасибо вам, так много! Не могу поверить, что задание, которое я провел пару дней, почти пропало из-за такой маленькой ошибки, спасибо! – woshidashen

+0

Нет проблем. Я рад помочь. – synchronizer

0

Одной из типичных ошибок является выделение памяти не для размера структуры, а для указателя на нее. Synchronizer показал solution проблемы в своем ответе:

struct node *p = malloc(sizeof(struct node)); 

Я должен также добавить, что таНос может возвращать потенциально нулевой указатель (link), поэтому после того, как выделение памяти должно быть проверено на нуль перед тем разыменованием:

struct node* createnode(int num) 
{ 
    struct node *p = malloc(sizeof(struct node)); 
    if (p != NULL)        // <= 
    { 
    p->data = num; 
    } 
    return p; 
} 

Очень жаль, что потребовалось столько времени, чтобы найти ошибку. Возможно, использование статических анализаторов могло бы помочь найти ошибки раньше. Here вы можете видеть, как подобная ошибка может быть совершена в крупных проектах.

+0

Привет, спасибо за ответ, который действительно полезен! Интересно, может ли функция malloc вернуть потенциально нулевой указатель, как я могу создать узел и добавить определенное значение к его данным, если указатель имеет значение null? Если я выделил память для определяемого мной узла, должна ли в памяти быть все то, что я определил для этого узла? – woshidashen

+0

'malloc' возвращает нулевой указатель только при плохих обстоятельствах. Такая ситуация может возникнуть в случае нехватки памяти, или, возможно, память слишком фрагментирована, и вы не можете получить линейный кусок памяти.Поэтому важно проверить указатель после выделения памяти, потому что разыменование нулевого указателя приводит к [неопределенному поведению] (http://en.cppreference.com/w/cpp/language/ub). Если память была выделена (размер «узла» в вашем случае), после нажатия указателя 'void' указателя' node' все рабочие поля будут доступны для работы. –

+0

Получил, спасибо! – woshidashen

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