【问题标题】:Cannot access memory error for character array in struct - C无法访问结构中字符数组的内存错误 - C
【发布时间】:2020-09-17 08:34:15
【问题描述】:

我正在尝试使用 C 中的链表创建队列。我使用两个结构来表示队列和每个节点,如下所示。

#define DATA_MAX 100

struct QueueNode_ch 
{
    struct QueueNode_ch* next;
    char data[(DATA_MAX + 1)];
};
typedef struct QueueNode_ch QueueNode_ch;

struct Queue_ch
{
    struct QueueNode_ch* front;
    struct QueueNode_ch* rear;
    int count;
};
typedef struct Queue_ch Queue_ch;

然后我使用以下这些函数来初始化队列和节点。

int initQueue_ch(Queue_ch* q)
{
    q = (Queue_ch*)malloc(sizeof(Queue_ch));
    q->count = 0;
    q->front = NULL;
    q->rear = NULL;
    return 0;
}

int initQueueNode_ch(QueueNode_ch* node)
{
    node = (QueueNode_ch*)malloc(sizeof(QueueNode_ch));
    node->next = NULL;
    node->data[0] = '\0';
    return 0;
}

在运行我的 enqueue 函数时,由于 strcpy 函数而出现段错误,并且在调试 gdb 时说它无法访问我尝试添加的节点的内存。入队代码如下:

int enqueue_ch(Queue_ch* q, char* data)
{
    if(strlen(data) > (DATA_MAX + 1))
        return 1;
    QueueNode_ch* tmp;
    initQueueNode_ch(tmp);
    strncpy(tmp->data, data, DATA_MAX);
    if(isEmpty_queue_ch(q))
        q->rear = q->front = tmp;
    else
    {
        q->rear->next = tmp;
        q->rear = tmp;
    }
    q->count++;
    return 0;
}

我还将包括我的主要功能作为附加信息。

#include <stdio.h>
#include "Queue.h"

int main()
{
    Queue_ch* queue;
    initQueue_ch(queue);
    enqueue_ch(queue, "hello");
    return 0;
}

据我所知,应该有足够的空间将给定的字符串复制到节点。有人知道什么是失败和可能的修复吗?

【问题讨论】:

  • (Queue_ch* q) { q = 参数按值传递。原来的queue没有初始化。
  • 关于:if(strlen(data) &gt; (DATA_MAX + 1)) 函数strlen()将OFFSET返回到尾随的NUL字节,建议:if( strlen( data) &gt; DATA_MAX )

标签: c struct queue singly-linked-list function-definition


【解决方案1】:

正如其他人所提到的,您正在按值传递结构。在 C 中,执行此操作的正确方法是使用指向指针的指针。请注意,我没有尝试编译这个,但希望这个想法很清楚。

int initQueue_ch(Queue_ch** q)
{
    *q = (Queue_ch*)malloc(sizeof(Queue_ch));
    (*q)->count = 0;
    (*q)->front = NULL;
    (*q)->rear = NULL;
    return 0;
}

int initQueueNode_ch(QueueNode_ch** node)
{
    *node = (QueueNode_ch*)malloc(sizeof(QueueNode_ch));
    (*node)->next = NULL;
    (*node)->data[0] = '\0';
    return 0;
}

【讨论】:

  • 啊,我明白了。这解决了问题。谢谢!
  • @Peter 很高兴为您提供帮助。除了malloc,您还可以使用calloc,而不是将成员显式设置为NULL0。节省了几行代码。
【解决方案2】:

函数initQueue_ch 没有意义。

int initQueue_ch(Queue_ch* q)
{
    q = (Queue_ch*)malloc(sizeof(Queue_ch));
    q->count = 0;
    q->front = NULL;
    q->rear = NULL;
    return 0;
}

函数参数q是函数的局部变量。更改函数中的变量不会影响提供给函数的参数。

此外,动态分配队列也没有意义。该函数可以如下所示

void initQueue_ch( Queue_ch *q )
{
    q->count = 0;
    q->front = NULL;
    q->rear  = NULL;
}

而在 main 你可以写

Queue_ch queue;
initQueue_ch( &queue );

函数initQueueNode_ch也存在同样的问题

int initQueueNode_ch(QueueNode_ch* node)
{
    node = (QueueNode_ch*)malloc(sizeof(QueueNode_ch));
    node->next = NULL;
    node->data[0] = '\0';
    return 0;
}

该函数再次处理传递参数值的副本。更改副本不会影响原始参数。

函数整体没有意义。你需要的是一个分配新节点的函数。

例如可以这样看

QueueNode_ch * createQueueNode_ch( const char *data )
{
    QueueNode_ch *node = malloc( sizeof( QueueNode_ch ) );

    if ( node != NULL )
    {
        node->next = NULL;
        strcpy( node->data, data );
    }

    return node;
}

函数enqueue_ch具有通过值传递指向队列的指针的相同缺点,看起来像

int enqueue_ch( Queue_ch *q, const char *data )
{
    int success = strlen( data ) < DATA_MAX + 1;

    if ( success )
    {
        QueueNode_ch *node = createQueueNode_ch( data );

        success = node != NULL;

        if ( success )
        {
            if ( q->rear == NULL )
            {
                q->front = q->rear = node;
            }
            else
            {
                q->rear = q->rear->next = node;
            }

            ++q->count;
        }
    }

    return success;
}

这是一个演示程序。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DATA_MAX 100

struct QueueNode_ch 
{
    struct QueueNode_ch* next;
    char data[(DATA_MAX + 1)];
};
typedef struct QueueNode_ch QueueNode_ch;

struct Queue_ch
{
    struct QueueNode_ch* front;
    struct QueueNode_ch* rear;
    int count;
};
typedef struct Queue_ch Queue_ch;

void initQueue_ch( Queue_ch *q )
{
    q->count = 0;
    q->front = NULL;
    q->rear  = NULL;
}

QueueNode_ch * createQueueNode_ch( const char *data )
{
    QueueNode_ch *node = malloc( sizeof( QueueNode_ch ) );

    if ( node != NULL )
    {
        node->next = NULL;
        strcpy( node->data, data );
    }

    return node;
}

int enqueue_ch( Queue_ch *q, const char *data )
{
    int success = strlen( data ) < DATA_MAX + 1;

    if ( success )
    {
        QueueNode_ch *node = createQueueNode_ch( data );

        success = node != NULL;

        if ( success )
        {
            if ( q->rear == NULL )
            {
                q->front = q->rear = node;
            }
            else
            {
                q->rear = q->rear->next = node;
            }

            ++q->count;
        }
    }

    return success;
}

void deleteQueue_ch( Queue_ch *q )
{
    while ( q->front != NULL )
    {
        QueueNode_ch *node = q->front;
        q->front = q->front->next;
        free( node );
    }

    q->rear = q->front;
    q->count = 0;
}

int main(void) 
{
    Queue_ch queue;
    initQueue_ch( &queue );

    enqueue_ch( &queue, "hello" );

    deleteQueue_ch( &queue );

    return 0;
}

【讨论】:

    【解决方案3】:
    int initQueue_ch(Queue_ch* q)
    {
        q = (Queue_ch*)malloc(sizeof(Queue_ch));
        q->count = 0;
        q->front = NULL;
        q->rear = NULL;
        return 0;
    }
    

    此功能无法使用。它忽略传递给它的q 的值,并且不返回指向它初始化的队列的指针。 C 严格按值传递。

    int main()
    {
        Queue_ch* queue;
        initQueue_ch(queue);
        enqueue_ch(queue, "hello");
        return 0;
    }
    

    这段代码从不给queue 任何值,并将垃圾值传递给initQueue_ch(它会忽略),然后将垃圾值传递给enqueue_ch

    【讨论】:

    • 好吧,我明白我的错误了。感谢您的帮助!
    【解决方案4】:

    如果您使用 malloc() 进行初始化,则返回指针() 而不是像下面那样将指针传递给函数。

    struct wordlist* wordlist_create(void)
    {
        struct wordlist* wordListPtr = (struct wordlist*) malloc(sizeof(struct wordlist));
        wordListPtr->count = 0;
    
        wordListPtr->root = getTrieNode();
    
        return wordListPtr;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-02
      • 2016-06-30
      • 2023-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多