【问题标题】:Issue with Segmentation fault分段错误的问题
【发布时间】:2014-02-20 14:00:41
【问题描述】:

我有这个结构:

typedef struct Msg 
{
    MsgType msgType;
    INT   msgLen;
    VOID *pMessage;
    UINT No; 
}Msg;

我已经定义了一个指针:

Msg *startPointer = NULL;

那我在做:

startPointer =  (Msg *)RxBufferArray[trackSN].IntMsg;

在哪里

RX_BUFFER_STRUCT RxBufferArray[100];

typedef struct RX_BUFFER_STRUCT_T {
    UINT seqNum;
    Msg *IntMsg;
} RX_BUFFER_STRUCT;

那我在做:

temp = (U32 *)startPointer->pMessage;

这给了我一个分段错误。 RxBufferArray[trackSN].IntMsg 的值为 0x0(来自 gdb),trackSN 为 1。

当我点击语句:temp = (U32 *)startPointer->pMessage;,当我尝试打印 startPointer->pMessage 的值时,它说:Cannot访问地址 0x8 处的内存

对解决问题有帮助吗?

【问题讨论】:

  • 指针指向的是不确定的。
  • 你在哪里初始化了数组RxBufferArray?如果不初始化,就会导致这种情况。
  • 你在哪里为RxBufferArray[trackSN].IntMsg分配内存?
  • 谁能帮我初始化 RxBufferArray 或 RxBufferArray[trackSN].IntMsg?我只有全局声明的 RX_BUFFER_STRUCT RxBufferArray[100];陈述。我也在填写 RxBufferArray[ctxt.seqNum].IntMsg = temppIntMsg;在其他一些功能中。 temppIntMsg 也属于同一类型的“Msg”,并且已填充值。
  • 有什么帮助吗?

标签: c pointers struct gdb segmentation-fault


【解决方案1】:

没有问题,是吗?

你说IntMsg是0,所以这个:

 startPointer = (Msg *) RxBufferArray[trackSN].IntMsg;

startPointer 设置为 0。然后取消引用该无效指针,导致未定义的行为(段错误)。

类型的混合非常令人困惑,对我来说,很难理解您试图在这里实现什么。

【讨论】:

    【解决方案2】:
    typedef struct RX_BUFFER_STRUCT_T {
        UINT seqNum;
        Msg *IntMsg; //this is just pointer, no structure behind it
    } RX_BUFFER_STRUCT;
    

    您不会为 RX_BUFFER_STRUCT 数组中的每个“Msg”结构分配内存。

    我看到了两种解决方法。所有这些都基于您使用的编程原则。 首先,如果你只是用数据填充你的“Msg”结构:

    typedef struct RX_BUFFER_STRUCT_T {
        UINT seqNum;
        Msg IntMsg; //now this is not pointer, this is structure here
    } RX_BUFFER_STRUCT;
    

    并使用:

    startPointer =  (Msg *)&RxBufferArray[trackSN].IntMsg; //I added "&" 
    temp = (U32 *)startPointer->pMessage;
    

    第二,当你得到已经填充的结构时:

    typedef struct RX_BUFFER_STRUCT_T {
        UINT seqNum;
        Msg *IntMsg = 0; //this is still pointer
    } RX_BUFFER_STRUCT;
    

    添加数据:

    Msg *tempMsg = (Msg*)calloc(sizeof(Msg));
    memcpy(tempMsg, inputMsg, sizeof(Msg)); //inputMsg is pointer to filled structure
    RxBufferArray[trackSN].IntMsg = tempMsg;
    

    使用数据:

    if(RxBufferArray[trackSN].IntMsg == 0){
        return;
    }else{
        startPointer =  (Msg *)RxBufferArray[trackSN].IntMsg;
        temp = (U32*)startPointer->pMessage;
    }
    

    现在你首先检查你是否有填充结构,然后使用数据。

    UPD:如何添加数据:

    //global variables
    int buffer_head = 0; //for writing
    int buffer_tail = 0; //for reading
    RX_BUFFER_STRUCT RxBufferArray[100];
    
    void addData(Msg *inputMsg){
        Msg *tempMsg = (Msg*)calloc(sizeof(Msg));
        memcpy(tempMsg, inputMsg, sizeof(Msg)); //inputMsg is pointer to filled structure
        RxBufferArray[buffer_head++].IntMsg = tempMsg;
    }
    
    //main function for example
    int main(){
        Msg message; //creates structure
        message.pMessage = calloc(30*sizeof(char)); //allocates memory for message string
        message.msgLen = sprintf((char*)message.pMessage, "Test message"); //fills message
        addData(&message); //adds message to buffer
    return 0;
    }
    

    【讨论】:

    • inputMsg 是什么类型以及如何将其指向填充的结构?请帮忙。
    • 感谢您的更新。我的问题是,当您从 main 调用 addData 时,是否只会更新 RxBufferArray 的一个索引?还是全部100?我认为只有一个,那就是第 0 个索引。是吗?而当我们尝试取消引用索引 1 时,会发生与之前相同的事情(崩溃)吗?
    • 发生崩溃是因为“RxBufferArray[trackSN].IntMsg”没有指向任何地方。当它指向任何地方时,你就无法访问它。
    • 发生崩溃是因为“RxBufferArray[trackSN].IntMsg”没有指向任何地方。当它指向任何地方时,您将无法访问它。现在我们创建一些指向的地方并将其应用于我们的指针。我们控制位于 0.."buffer_head" 单元中的所有填充结构。即使我们想访问任何随机数组单元,我们也会检查“RxBufferArray[trackSN].IntMsg”是否是正确的指针(不是 0)。使用一个 addData 我们只更改数组中一个单元格的内容,而不是全部 100 个单元格。如果你想从这个数组中读取数据,你只需要访问 0..buffer_head 单元格。不高于 buffer_head。
    【解决方案3】:

    在你的结构中:

    typedef struct RX_BUFFER_STRUCT_T {
        UINT seqNum;
        Msg *IntMsg;
    } RX_BUFFER_STRUCT;
    

    当你声明一个RX_BUFFER_STRUCT 的数组时,它不会初始化IntMsg 指针,并且应该明确地为它分配内存。这就是当您尝试引用它时的原因,它是NULL

    现在,当你做这个任务时:

    startPointer =  (Msg *)RxBufferArray[trackSN].IntMsg;
    

    应谨慎处理不同结构之间的类型转换。 startPointer->pMessage 只查看 RxBufferArray[trackSN] 的 Memory address + sizeof(UINT) 可能是 0x8 并且由于该内存未初始化,因此无法访问,您会看到错误 cannot access memory at address 0x8

    【讨论】:

    • 您能建议更改吗?不确定如何初始化以及在哪里初始化。
    猜你喜欢
    • 2010-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多