帧成一个大的1D阵列

时间:2014-01-10 22:38:35

标签: c sockets winsock

我正在通过TCP从LabVIEW向此C程序发送单个灰度帧(160x120)。我设法将字节转换为uint32像素值。这里的目标是我将每个19203字节定义为一个图像数组,其中第一个字节是定义数组ID的头,第二个和第三个字节定义分辨率(120和160),最后19200个字节是从LabVIEW程序接收的字节数。目的是第一个数组的第一个字节将获得值“1”,第二个数组的第一个字节将获得值“2”,依此类推。

当我检查19203字节时,会发生这种情况的问题。我可以清楚地看到每个uint32值似乎都是正确的,直到值4801.从该值到19203,我得到一个恒定的奇怪值:“3435973836”,这与灰度像素无关,因为它只能在0和0之间。 300.错误发生在哪里?。

Result

#define DEFAULT_BUFLEN 19203

int main(int argc , char *argv[])
{
    WSADATA wsa;
    SOCKET s , new_socket;
    struct sockaddr_in server , client;
    int c;
    int iResult;
    int receivedCount = 0;
    char recvbuf[DEFAULT_BUFLEN];
    int recvbuflen = DEFAULT_BUFLEN;
    typedef unsigned int uint8_t;
    unsigned long totalReceived = 0, totalExpected=160*120;
    unsigned int i;
    uint32_t image[DEFAULT_BUFLEN]; 
    size_t len;
    uint8_t* p;
    uint8_t value;
    int x=0;
    int z=0;

    p = (uint8_t*)recvbuf;

    do
    {
        iResult = recv( new_socket, recvbuf, recvbuflen, 0);
        for(z=1; z<11; z++)
        {
            image[0] = z;

            for(i=0, x=1; i<19202,x<19203; i++, x++)
            {
                image [x] = p[i];
                printf("%lu\n",image[x]);
            }
        }   
    }
    while(iResult > 0 );

    closesocket(new_socket);
    WSACleanup();

    return 0;
}

3 个答案:

答案 0 :(得分:2)

recv()可能不一定会读取您要求的所有字节 - 它可能返回的字节数比您要求的少。您需要始终检查recv()的返回值,并且只处理那么多字节。通过忽略返回值,您将读取未初始化的内存。

数字3435973836在十六进制中更明确 - 它是0xcccccccc。 Visual Studio运行时使用此magic number来初始化Debug构建中的堆栈内存,因此当您看到该值时,您知道您正在读取未初始化的堆栈内存。

答案 1 :(得分:0)

检查DEFAULT_BUFLEN大小,因为我在代码中看不到它的声明。也许这会导致缓冲区溢出,因为array image []在声明时将它用作参数。

答案 2 :(得分:0)

你的缓冲区长19203 bytes ,但是你用 uint32 进行迭代,所以一次只有4个字节:

uint32_t image[DEFAULT_BUFLEN]; 
[...]
for(i=0, x=1; i<19202,x<19203; i++, x++)
{
    image [x] = [...];

// sizeof(uint32) == 4

因此,当您尝试阅读索引uint32的{​​{1}}时,您会在缓冲区外阅读:

4801

要考虑的另一件事是循环中的条件sizeof(uint32) * 4801 == 19204 using image[4801] is undefined behaviour, even image[4800] is ub 应该用i<19202,x<19203替换,前者使用逗号运算符,这与逻辑连接不同。