C 链表 - 条件跳转或移动取决于未初始化的值链表



嘿伙计们,

所以我在做这个双向链表代码,编译工作......但执行给了我 SIGSEGV。当我尝试运行 valgrind 时,它说有一些未初始化的值。

我最好的猜测是发生这种情况是因为malloc的内存范围达到或像.. idk一样,也许当函数结束时它会被转储?..我不确定,但它仍然说有一些内存已分配且可访问......或者也许只是一些我不知道的语义错误:/

瓦尔格林德 --曲目起源=是的:

Conditional jump or move depends on uninitialised value(s)
==14798==    at 0x400848: push (in /home/mename/linkedlist/llist)
==14798==    by 0x40088E: main (in /home/mename/linkedlist/llist)
==14798==  Uninitialised value was created by a heap allocation
==14798==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14798==    by 0x400879: main (in /home/mename/linkedlist/llist)
==14798== Use of uninitialised value of size 8
==14798==    at 0x4E8476B: _itoa_word (_itoa.c:179)
==14798==    by 0x4E8812C: vfprintf (vfprintf.c:1631)
==14798==    by 0x4E8F898: printf (printf.c:33)
==14798==    by 0x400793: printlist (in /home/mename/linkedlist/llist)
==14798==    by 0x4008CD: main (in /home/mename/linkedlist/llist)
==14798==  Uninitialised value was created by a heap allocation
==14798==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14798==    by 0x400879: main (in /home/mename/linkedlist/llist)
==14798== Invalid write of size 8
==14798==    at 0x40071B: pop (in /home/mename/linkedlist/llist)
==14798==    by 0x4008D9: main (in /home/mename/linkedlist/llist)
==14798==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==14798== Process terminating with default action of signal 11 (SIGSEGV)
==14798==  Access not within mapped region at address 0x0
==14798==    at 0x40071B: pop (in /home/mename/linkedlist/llist)
==14798==    by 0x4008D9: main (in /home/mename/linkedlist/llist)
==14798==  The main thread stack size used in this run was 8388608.
0 -> 0 -> 0 -> 0 -> 0==14798== 
==14798== HEAP SUMMARY:
==14798==     in use at exit: 96 bytes in 4 blocks
==14798==   total heap usage: 6 allocs, 2 frees, 1,144 bytes allocated
==14798== 
==14798== LEAK SUMMARY:
==14798==    definitely lost: 0 bytes in 0 blocks
==14798==    indirectly lost: 0 bytes in 0 blocks
==14798==      possibly lost: 0 bytes in 0 blocks
==14798==    still reachable: 96 bytes in 4 blocks
==14798==         suppressed: 0 bytes in 0 blocks

编辑:

添加了其他函数及其库(pop;清除列表;*.h) 根据答案建议更改/更新文件


清除列表.h

#ifndef CLEARLIST_H
#define CLEARLIST_H
#include "defs.h"
#include <stdlib.h>
int clearlist(node** head);
#endif

#ifndef POP_H
#define POP_H
#include "defs.h"
#include <stdlib.h>
int pop(node** head);
#endif

打印列表.h

#ifndef PRINTLIST_H
#define PRINTLIST_H
#include "defs.h"
#include <stdlib.h>
#include <stdio.h>
int printlist(node* head);
#endif

普什.h

#ifndef PUSH_H
#define PUSH_H
#include <stdlib.h>
#include "defs.h"
int push(node** head, int datainput);
#endif

defs.h

#ifndef DEFS_H
#define DEFS_H
#define SUCCESS 0
#define FAIL -1
#define TRUE 0
#define FALSE -1
#define ALLOCFAIL -2
#define EMPTY -3
typedef struct Node{
struct Node* next;
struct Node* prev;
int data;
} node;
#endif

主.c

#include "defs.h"
#include "clearlist.h"
#include "pop.h"
#include "printlist.h"
#include "push.h"
int main(){
node *head;
head = (node*) malloc(sizeof(node));
push(&head, 10);    
push(&head, 20);    
push(&head, 30);    
push(&head, 40);    
printlist(head);
pop(&head);
printlist(head);
clearlist(&head);
return SUCCESS;
}

我将只显示所涉及的函数,直到核心转储,我认为这是导致错误的原因。

普什.c

#include "push.h"
int push(node** head, int datainput){
/* Initialization of new node */
node* newptr = (node*) malloc(sizeof(node));    
if(newptr == NULL){
return ALLOCFAIL;
}
newptr->next = NULL;
newptr->data = datainput;
/* Check for empty list */
if(head == NULL){
newptr->prev = NULL;
*head = newptr;
return SUCCESS;
}
/* Get to the end of list*/
node* headptr = *head;
while(headptr->next != NULL){
headptr = headptr->next;        
}
headptr->next = newptr;
newptr->prev = headptr;
return SUCCESS;
}

打印列表.c

#include "printlist.h"
int printlist(node* head){
/* Check if valid node or empty list */
if(head == NULL){
return EMPTY;
}
/* Move to first node if not already */
node* firstptr = head;
while(firstptr->prev != NULL){
firstptr = firstptr->prev;
}
/* Print entire list*/
while(firstptr != NULL){
if(firstptr->next != NULL){
printf("%d -> ", firstptr->data);
}
else{
printf("%d", firstptr-->data);
}
firstptr = firstptr->next;
}
return SUCCESS;
}

流行.c

#include "defs.h"
#include "pop.h"
#include <stdio.h>
int pop(node** head){
/* If no node to pop */
if(*head == NULL){
return EMPTY;
}
/* Get to the end of list */
node* headptr = *head;
while(headptr->next != NULL){
headptr = headptr->next;        
}
/*Pop last*/ 
node* temp = headptr->prev;
free(headptr);
/* po temp - Check if deleted the only node left*/
if(temp = NULL){
*head = NULL;
return EMPTY;
}
/* ...if not, make previous node the last node  */
temp->next = NULL;
headptr = NULL;
return SUCCESS; 
}

clearlist.c

#include "clearlist.h"
int clearlist(node** head){
if(*head == NULL){
return SUCCESS;
}
/* Go to start */
while((*head)->prev != NULL){
*head = (*head)->prev;
}
/* Delete to the end */
while(*head != NULL){
node *prevnode = *head;
*head = (*head)->next;
free(prevnode);
}
return SUCCESS;
}

感谢您的帮助!

我真的不想要求一个完整的解决方案,我想学习一些新的东西,但我有点坚持在这个解决方案上。 :)

问题是mallocing 不会初始化任何内容,例如:

node *head;
head = (node*) malloc(sizeof(node));

节点的值可以是任何内容,您需要将指针设置为 NULL

head->prev = head->next = NULL;

此外,您应该在一行上声明和初始化节点,并且不要强制转换 malloc 的结果,我还推荐另一种sizeof机制。如果您使用的是 C99 或更高版本,则有一种更强大的方法来零初始化node中的所有内容,即使用复合文字

node* head = malloc(sizeof *head);
*head = (node){0};

查看其余代码,如果这在任何地方都是相同的问题,我并不肯定,但为了您自己的安全,您应该遵循上述模式。

问题是这样的:

int main(){
node *head;
head = (node*) malloc(sizeof(node));
push(head, 10);
...
}

head只分配,不初始化!

当您将未初始化的指针传递给push时,

if(head == NULL)

将为假,并且块不会被执行,但是下一个块

node* headptr = head;
while(headptr->next != NULL){
headptr = headptr->next;        
}

被执行。Remeberhead未初始化,因此headptr->next指向 无处可去,您分配headptr = heatdptr->next等等。 Valgrind 告诉你:未初始化的值是由堆分配创建的

push函数应采用双指针指向head并更改其位置 指向创建新头部的时间:

int push(node **head, int datainput){
/* Initialization of new node */
node* newptr = (node*) malloc(sizeof(node));    
if(newptr == NULL){
return ALLOCFAIL;
}
newptr->next = NULL;
newptr->data = datainput;
/* Check for empty list */
if(*head == NULL){
newptr->prev = NULL;
*head = newptr; // change where head is pointing to
return SUCCESS;
}
/* Get to the end of list*/
node* headptr = *head;
while(headptr->next != NULL){
headptr = headptr->next;        
}
headptr->next = newptr;
newptr->prev = headptr;
return SUCCESS;
}

然后你可以这样称呼它:

int main(){
node *head = NULL; // <-- important initialization
push(&head, 10);
push(&head, 20);
...
}

另请注意:不要投malloc


编辑

printlist也有一个小错误,你只是打印头部, 正确的版本应该是

int printlist(node* head){
/* Check if valid node or empty list */
if(head == NULL){
return EMPTY;
}
/* Move to first node if not already */
node* firstptr = head;
while(firstptr->prev != NULL){
firstptr = firstptr->prev;
}
/* Print entire list*/
while(firstptr != NULL){
if(firstptr->next != NULL){
printf("%d -> ", firstptr->data);
}
else{
printf("%d", firstptr->data);
}
firstptr = firstptr->next;
}
puts("");
return SUCCESS;
}

请注意,C 没有通过引用传递,因此如果要修改值 对于其他函数中的变量,您将指针传递给该变量:

void foo(int *p)
{
*p = 8;
}
void bar(void)
{
int c = 4;
foo(&c);
// c is now 8
}

这同样适用于指针,如果你想改变指针指向的位置。 在另一个函数中,您必须将指针传递给指针(又名双精度 指针):

void foo(char **str)
{
*str = "World";
}
void bar(void)
{
char *x = "Hello";
puts(x); // prints Hello
foo(&x);
// x points now to a different string literal
puts(x); // print World
}

这就是我在push所做的.

要证明这是正确的,请参阅以下内容:https://ideone.com/As5XDy

我已经使用了我的push函数(以及printlist的修复),输出是

10 -> 20 -> 30 -> 40

另外不要忘记编写一个释放内存的函数。

相关内容

  • 没有找到相关文章

最新更新