strstr()函数返回地址0x0000

时间:2016-04-30 11:29:16

标签: c avr

我试图通过strstr()函数检查子串(" DATA")是否(及其位置)位于一个大字符串(位于缓冲区 - linearBuffer中),但它似乎不起作用,我不知道为什么我的源字符串(位于linearBuffer中)以null结束。

真正的问题是,每个USART中断都会有一个环形缓冲区(buf)填充字符。然后,在代码的某个点上,将其内容复制到线性缓冲区(通过ringBuff_to_linearBuff())并在其上应用strstr()函数,以便找到想要的子字符串。函数strstr()返回时得到的值是值244而不是子字符串的位置,尽管我知道它在设置断点时的位置

**请注意,我的代码分布在许多文件中,因此我尝试将所有与问题相关的代码收集在一起。

#include <string.h>

#define BUFFER_SIZE           400
#define LINEAR_BUFFER_SIZE (BUFFER_SIZE+1)
#define WIFI_CMD_DATA   "DATA"

typedef RingBuff_Data_t        uint8_t;

typedef struct
{
    RingBuff_Data_t  Buffer[BUFFER_SIZE]; /**< Internal ring buffer data, referenced by the buffer pointers. */
    RingBuff_Data_t* In; /**< Current storage location in the circular buffer */
    RingBuff_Data_t* Out; /**< Current retrieval location in the circular buffer */
} RingBuff_t;

volatile RingBuff_t buf;
uint8_t linearBuffer[LINEAR_BUFFER_SIZE]="";

static inline void RingBuffer_Insert(RingBuff_t* const Buffer, const RingBuff_Data_t Data)
{
    *Buffer->In = Data;

    if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
              Buffer->In = Buffer->Buffer;

    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
    {
        Buffer->Count++;
    }
}

ISR(USART1_RX_vect)
{
    //code to be executed when the rx pin of the USART receives a char
    uint8_t c = UDR_N;
    if (c != '\n')
        RingBuffer_Insert(&buf,c);
    else
        RingBuffer_Insert(&buf,'\0');
}

void ringBuff_to_linearBuff(uint8_t linearBuffer[])
{
    memset(linearBuffer,0,LINEAR_BUFFER_SIZE);
    RingBuff_Data_t* tempIn = buf.In;
    if (buf.Out < tempIn){
        memcpy(linearBuffer, buf.Out, tempIn - buf.Out);
    }
    else if (buf.Out > tempIn){
        size_t s1 = buf.Buffer + BUFFER_SIZE - buf.Out;
        size_t s2 = buf.In - buf.Buffer;
        memcpy(linearBuffer, buf.Out, s1);
        memcpy(linearBuffer + s1, buf.Buffer, s2);
    }
}

void main () 
{
    uint8_t* linearBufferp;
    while (1)
    {
        if (buf.Out != buf.In)
        {
            ringBuff_to_linearBuff(linearBuffer);
            linearBufferp = strstr(linearBuffer, WIFI_CMD_DATA); // Checking if a new DATA msg from a client had arrived
            if (linearBufferp != NULL)
            {
                //do something
            }
        }
    }
}

debugging

1 个答案:

答案 0 :(得分:1)

<tbody> <% @tasks.each do |task| %> <tr> <td><%= task.title %></td> <td><%= task.note %></td> <td><%= task.created_at.strftime("%A,%B,%Y") %></td> </tr> <% end %> #this ends the @task.each do loop </tbody> </table> <% end %> #this ends the if else conditional 返回NULL时,意味着它没有找到子字符串(当发生这种情况时,它指向的值根本没有意义,所以忘掉224)。

所以你的问题应该是:

  

为什么strstr找不到我的子串?

查看您发布的调试图片时,strstr包含:

linearBuffer

但是,缓冲区中有多个字符串:

13
 0
13
 0
43
....
....
68      <---- This is what you want to find
65
....

13 <----- Start of first string 0 <----- End of first string 13 <----- Start of second string 0 <----- End of second string 43 <----- Start of thrid string .... .... 68 <---- This is what you want to find 65 .... 只搜索第一个字符串。当strstr看到第一个strstr(索引[1])时,它会返回0,因为它找不到它要查找的内容。

换句话说 - NULL永远不会查看匹配所在的缓冲区部分。它在此之前就已经很久了。

  

你的代码出了什么问题?

由于您尚未发布完整的代码库,因此很难说。所以这是猜测。我认为你会收到一些形式的“换行符”:

strstr

之前的消息。所以你收到了:

13 10 13 10

您的ISR将13 10 13 10 43 ...... 68 65 ..... 转换为10,因此缓冲区变为

0

这是3个字符串而不是1个字符串。

  

怎么办?

嗯,可能有几种不同的解决方案。正确取决于您的系统要求。一个简单的解决方案是在调用13 0 13 0 43 ...... 68 65 ..... 之前跳过额外的13 0。类似的东西:

strstr

注意:您还应该添加一些范围检查,以便ringBuff_to_linearBuff(linearBuffer); // Skip "13 0" while (*linearBuffer == 13 && *(linearBuffer+1) == 0) { linearBuffer += 2; } linearBufferp = strstr(linearBuffer, WIFI_CMD_DATA); 不会增加太多以至于您读出界限