Valgrind error: Invalid write of size 8 while using lists made of struct and malloc
Valgrind error: Invalid write of size 8 while using lists made of struct and malloc
我对 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
注意,如果你需要在函数中访问列表的最后一个节点,那么最好将singly-linked列表定义为two-sidedsingly-linked列表。
例如
typedef struct lista_t
{
nodo_t *head;
nodo_t *tail;
} lista_t;
我对 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
注意,如果你需要在函数中访问列表的最后一个节点,那么最好将singly-linked列表定义为two-sidedsingly-linked列表。
例如
typedef struct lista_t
{
nodo_t *head;
nodo_t *tail;
} lista_t;