问题描述
我对Valgrind有问题,今天是我开始使用它的第一天,我真的不习惯。 这是我的代码:
//list' typedef
typedef struct nodo_s {
int n;
struct nodo_s * next;
} nodo_t;
//function with error
void cambiaDirezionesinistra(nodo_t * head)
{
nodo_t * tmp,*temp;
for(tmp = head; tmp != NULL; tmp = tmp->next)
;
printf("1s: %d\n",tmp->n);
temp = head;
printf("2s: %d\n",temp->n);
head = temp->next;
printf("3s: %d\n",head->n);
tmp->next = temp; ----> error
printf("4s: %d\n",tmp->n);
temp->next = NULL;
}
//main
int main()
{
int i;
int dir;
nodo_t * head = NULL;
for(i = 0; i < N; i ++)
head = nuovoNodo(head);
stampaLista(head);
printf("Inserisci la direzione di scambio,0 per sinistra e 1 per destra.\n");
scanf("%d",&dir);
if(dir == 0)
cambiaDirezionesinistra(head);
else if(dir == 1)
cambiaDirezioneDestra(head);
stampaLista(head);
return 0;
}
这是该错误的Valgrind报告:
==511== Invalid write of size 8
==511== at 0x10930F: cambiaDirezionesinistra (20200120_6.c:55)
==511== by 0x1094EE: main (20200120_6.c:103)
==511== Address 0x8 is not stack'd,malloc'd or (recently) free'd
==511==
==511==
==511== Process terminating with default action of signal 11 (SIGSEGV)
==511== Access not within mapped region at address 0x8
==511== at 0x10930F: cambiaDirezionesinistra (20200120_6.c:55)
==511== by 0x1094EE: main (20200120_6.c:103)
我尝试了很多在互联网上找到的“解决方案”,但是我无法以任何方式解决它。谢谢。
解决方法
函数cambiaDirezioneSinistra
具有未定义的行为。
对于初学者,指向头节点的指针按值传递。因此,该函数处理指向头节点的指针的值的副本。更改副本不会影响原始指针。
void cambiaDirezioneSinistra(nodo_t * head)
指向头节点的指针可以等于NULL。但是函数内没有检查head
是否等于NULL。
此循环后
for(tmp = head; tmp != NULL; tmp = tmp->next)
;
指针tmp
将等于NULL。因此,使用此指针访问结构的数据成员没有任何意义。
可以通过以下方式声明和定义函数
//function with error
void cambiaDirezioneSinistra( nodo_t **head )
{
if ( *head != NULL && ( *head )->next != NULL )
{
nodo_t *last = *head;
while ( last->next ) last = last->next;
last->next = *head;
*head = ( *head )->next;
last->next->next = NULL;
}
}
该函数的调用方式类似于
cambiaDirezioneSinistra( &head );
这是一个演示程序。
#include <stdio.h>
#include <stdlib.h>
//list' typedef
typedef struct nodo_s
{
int n;
struct nodo_s * next;
} nodo_t;
//function with error
void cambiaDirezioneSinistra( nodo_t **head )
{
if ( *head != NULL && ( *head )->next != NULL )
{
nodo_t *last = *head;
while ( last->next ) last = last->next;
last->next = *head;
*head = ( *head )->next;
last->next->next = NULL;
}
}
int append( nodo_t **head,int n )
{
while ( *head ) head = &( *head )->next;
*head = malloc( sizeof( nodo_t ) );
int success = *head != NULL;
if ( success )
{
( *head )->n = n;
( *head )->next = NULL;
}
return success;
}
void display( const nodo_t *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ",head->n );
}
puts( "null" );
}
void clear( nodo_t **head )
{
while ( *head )
{
nodo_t *tmp = *head;
*head = ( *head )->next;
free( tmp );
}
}
int main(void)
{
nodo_t *head = NULL;
const int N = 10;
for ( int i = 0; i < N; i++ ) append( &head,i );
display( head );
for ( int i = 0; i < N; i++ )
{
cambiaDirezioneSinistra( &head );
display( head );
}
clear( &head );
return 0;
}
其输出为
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 0 -> null
2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 0 -> 1 -> null
3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 0 -> 1 -> 2 -> null
4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 0 -> 1 -> 2 -> 3 -> null
5 -> 6 -> 7 -> 8 -> 9 -> 0 -> 1 -> 2 -> 3 -> 4 -> null
6 -> 7 -> 8 -> 9 -> 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> null
7 -> 8 -> 9 -> 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> null
8 -> 9 -> 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> null
9 -> 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> null
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
请注意,如果您需要访问函数中列表的最后一个节点,那么最好将单链接列表定义为双面单链接列表。
例如
typedef struct lista_t
{
nodo_t *head;
nodo_t *tail;
} lista_t;