嘿伙计们,
所以我在做这个双向链表代码,编译工作......但执行给了我 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;
}
感谢您的帮助!
我真的不想要求一个完整的解决方案,我想学习一些新的东西,但我有点坚持在这个解决方案上。 :)
问题是malloc
ing 不会初始化任何内容,例如:
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
另外不要忘记编写一个释放内存的函数。