我试过使用 GDB 和 Valgrind,但我似乎无法查明问题所在。 有趣的是,程序在正常执行和 GDB 期间崩溃,但 Valgrid 不会。
为了帮助您理解代码,下面是程序的基本要点: 通过套接字和 UDP 与服务器通信以传输文件,并处理一些基本的数据包丢失。
我不会分享服务器的代码,因为我知道问题不在那里。 可能会让一些人感到困惑的一点是,我正在使用一个数字生成器自己实现数据包丢失。现在它除了让程序使用另一个 recvfrom 之外什么也没做。
为了引导您完成程序输出,客户端告诉服务器它想要什么文件,服务器告诉客户端它要发送的文件有多大,然后分块发送(一次 10 个字符) .
输出显示发送了什么 block ,接收到多少个字符,以及连接的字符串是什么。
据我所知,文件传输成功了,它只是我用来写入接收到的文件的 fopen 调用给我带来了麻烦。不确定这是否与我的 malloc 调用有关。
这是源代码:
pastebin.com/Z79hvw6L
这是 CLI 执行和 Valgrind 的输出(GDB 似乎没有提供更多信息):
注意 CLI 给出了 malloc 内存损坏错误,而 Valgrind 没有。
命令行界面:http://pastebin.com/qdTKMCD2
瓦尔格林德:http://pastebin.com/8inRygnU
感谢您的帮助!
添加了 GDB 回溯结果
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x6b961)[0x19a961]
/lib/i386-linux-gnu/libc.so.6(+0x6e15d)[0x19d15d]
/lib/i386-linux-gnu/libc.so.6(__libc_malloc+0x63)[0x19ef53]
/lib/i386-linux-gnu/libc.so.6(+0x5c2b8)[0x18b2b8]
/lib/i386-linux-gnu/libc.so.6(fopen+0x2c)[0x18b38c]
/home/---/client[0x8048dc2]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xe7)[0x145e37]
/home/---/client[0x8048871]
也许这可以让某人了解错误出在程序的哪一部分?
最佳答案
char chunk[10];
chunk[10] = '\0';
错了,chunk[10] 是数组后面的一个。
一般来说,这样做要小心
char filename[25];
scanf("%s",filename);
如果你输入一个长文件名,你会浪费内存。使用 fgets() 会更好。您至少还需要检查 scanf 是否成功,否则文件名上的以下 strlen() 无效。
第 93 行,buf[strlen(buf)-1]='\0';
是危险的,如果缓冲区尚未以 nul 终止,则不能使用 strlen,并且您将其丢弃内存如果 buf 是一个空字符串,因为你索引 buf[-1]。
编辑。
您的另一个问题是 strcat(fullstring,chunk);
,如果您碰巧收到的数据多于它可以容纳的数据,您无法控制循环停止附加到该字符串。大小也可能会减少一个,因为您需要为最后一个 nul 终止符留出空间。让它至少 char * fullstring = malloc(sizeof(char)*filesize + 1 );
但是你的循环确实需要检查它是否没有写到缓冲区的末尾。
至于向 buf
添加 nul 终止符,recv 调用会返回您已读取的字节数,因此如果您已检查 recv 是否有错误,请执行 buf[numbytes] = 0
,但这也会被一个关闭,因为您已经为 buf
分配了 10 个字节,并且您也尝试将 10 个字节读入其中 - 但在 C 中,一个字符串也需要空终止符的空间。使 buf 变大 11 个字节。或者 recv() 只有 9 个字节。
事实上,您偏离了很多地方,所以开始计算您需要多少字节,以及您是否将内容放入其中。请记住,在 C 语言中,数组以索引 0 开始,而 10 的数组只能通过索引 0 到 9 进行索引。
关于c - malloc 内存损坏,fopen,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7824095/