Valgrind错误:使用由struct和malloc构成的列表时,大小为8的无效写入

米歇尔·波西奥(Michele Bosio)

我对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)

我已经尝试了很多在Internet上找到的“解决方案”,但是我无法以任何方式解决它。谢谢。

来自莫斯科的弗拉德

该函数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;

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Valgrind大小为8的神秘无效写入错误

来自分类Dev

大小8的无效读取,大小8(Valgrind)的无效写入

来自分类Dev

访问结构成员时valgrind无效的读/写错误

来自分类Dev

使用Valgrind在C中无效读取大小8的分段错误

来自分类Dev

为什么Valgrind在PETSc中分配char *时报告大小写为8的无效写入?

来自分类Dev

Valgrind-strcpy的大小为1的无效写入

来自分类Dev

即使对于NULL分配,大小8 valgrind的无效写入

来自分类Dev

使用valgrind时无效读取大小1

来自分类Dev

分段错误,大小为4的无效写入

来自分类Dev

我在C中运行Valgrind时收到大小为8的无效读取

来自分类Dev

cpp-valgrind-大小为8的无效读取

来自分类Dev

cpp-valgrind-大小为8的无效读取

来自分类Dev

正确使用strcpy()并避免在valgrind中读取和写入大小错误

来自分类Dev

释放由malloc / Valgrind错误分配的内存

来自分类Dev

使用malloc和free:下一个大小错误无效

来自分类Dev

解决 valgrind 中的无效写入错误

来自分类Dev

Valgrind:大小为1的无效读/写

来自分类Dev

Valgrind 错误无效读取大小 4

来自分类Dev

使用strcpy,malloc和struct时出现分段错误(内核已转储)

来自分类Dev

使用由纬度和经度构成的ID

来自分类Dev

Valgrind:抛出自定义异常时为“无效的读取大小1”

来自分类Dev

Valgrind:抛出自定义异常时,“读取大小为1无效”

来自分类Dev

Valgrind:无效读取的8号错误

来自分类Dev

Valgrind:无效读取的8号错误

来自分类Dev

无效的写入Valgrind

来自分类Dev

Valgrind无效写入

来自分类Dev

Valgrind 的无效写入

来自分类Dev

valgrind对大小1的无效读取(realloc使错误“释放后使用条件”)

来自分类Dev

Valgrind中大小为4的无效读/写

Related 相关文章

热门标签

归档