我正在通过TCP从LabVIEW向此C程序发送单个灰度帧(160x120)。我设法将字节转换为uint32像素值。这里的目标是我将每个19203字节定义为一个图像数组,其中第一个字节是定义数组ID的头,第二个和第三个字节定义分辨率(120和160),最后19200个字节是从LabVIEW程序接收的字节数。目的是第一个数组的第一个字节将获得值“1”,第二个数组的第一个字节将获得值“2”,依此类推。
当我检查19203字节时,会发生这种情况的问题。我可以清楚地看到每个uint32值似乎都是正确的,直到值4801.从该值到19203,我得到一个恒定的奇怪值:“3435973836”,这与灰度像素无关,因为它只能在0和0之间。 300.错误发生在哪里?。
#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;
}
答案 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
替换,前者使用逗号运算符,这与逻辑连接不同。