实现一个数据链接协议。我设法通过虚拟串行端口发送整个文件-这应该是困难的部分。奇怪的是,当我试图保存它时,我在fclose()上得到了一个segfault。文件正在创建,这意味着打开成功,但没有任何东西存储在其中。甚至改变了实现,在保存之前将所有文件缓冲到内存中。
int app_rx(const char* outputFile){
file_data_t fileData;
if(!receive_ctrl_pckt(&fileData)){
printf("Could not receive control packet\n");
return FAILURE;
}
printf("Receiving file [%s]\nFile size: %d\n", fileData.fileName, fileData.fileSize);
unsigned char fileBuffer[fileData.fileSize];
int fileIndex = 0;
int totalBytes = 0;
int stop = 0;
size_t sqNo = 0;
int bytes;
FILE* out = fopen(outputFile, "w");
do{
activeBuffer = (activeBuffer + 1) % 2;
printf("Receiving packet %lu\n", sqNo);
bytes = llread(BUFFERS[TMP_BUFFER]);
if(bytes == DUP_ERR){
printf("Duplicate data. Discarding packet\n");
}
else if (bytes == WH_ERR){
printf("Invalid header. Discarding packet\n");
}
else if (bytes == WD_ERR){
printf("Corrupted data. Awaiting retransmission\n");
}
else{
printf("Packet %lu successfully received\n", sqNo);
int retrieveRes = retrieve_payload(sqNo);
switch(retrieveRes){
case CTRL_END: {
stop = 1;
break;
}
case FAILURE: {
printf("Unknown error\nExiting...");
exit(1);
}
case SQ_ERR:{
printf("Unsynchronized packets\nExiting");
exit(1);
}
default:{
for(int i = 0; i < retrieveRes; i++){
fileBuffer[fileIndex] = BUFFERS[activeBuffer][i];
fileIndex++;
}
sqNo = (sqNo + 1) % 255;
totalBytes += bytes;
break;
}
}
}
}while(!stop);
printf("file index: %d\n", fileIndex);
fwrite(fileBuffer, sizeof(unsigned char), fileIndex, out);
printf("here\n");
fclose(out);
if(totalBytes == fileData.fileSize){
return SUCCESS;
}
else{
return FAILURE;
}
}
标准输出:
Packet 9 successfully received
Receiving packet 10
Asserting data integrity
Packet 10 successfully received
Receiving packet 11
Asserting data integrity
Packet 11 successfully received
file index: 10968
here
make: *** [Makefile:35: run_rx] Segmentation fault (core dumped)
我知道,这是一个很大的方法。只是想在正确重构之前把它弄清楚。不能为了什么而弄清楚发生了什么。我知道这是可行的,因为我已经用这个方法复制了完全相同的文件,用一个简单的copyfile.c测试驱动程序来模仿cp命令。
有什么想法吗?我发现它创建了输出文件,但没有在上面写任何东西,这特别奇怪。
编辑:在写之前打开文件,设法让它运行起来。仍然不太明白发生了什么
1条答案
按热度按时间qnakjoqk1#
数组fileBuffer存在潜在的缓冲区溢出风险,除非retrieveRes保证未来或等于fileData.fileSize,否则如果存在缓冲区溢出,则在调用fclose时,指针out可能会被覆盖并导致段错误。可以通过在do/while循环和调用fclose之前打印out的值来验证缓冲区溢出。