malloc 内存损坏、fopen
我尝试过使用 GDB 和 Valgrind,但我似乎无法查明问题所在。 有趣的是,程序在正常执行和 GDB 期间崩溃,但 Valgrid 却不会。
为了帮助您理解代码,以下是该程序的基本点: 通过套接字和 UDP 与服务器通信以传输文件,并处理一些基本的数据包丢失。
我不会分享服务器的代码,因为我知道问题不存在。 可能会让一些人感到困惑的是,我自己使用数字生成器来实现数据包丢失。现在除了让程序使用另一个recvfrom 之外,它实际上没有做任何事情。
为了引导您完成程序输出,客户端告诉服务器它想要什么文件,服务器告诉客户端要发送的文件有多大,然后分块发送(一次 10 个字符)。
输出显示发送了哪些块、接收了多少个字符以及连接的字符串是什么。
据我所知,文件传输成功,这只是我用来写入接收到的文件的 fopen 调用给我带来了麻烦。不确定这是否与我的 malloc 调用有关。
这是源代码:
pastebin.com/Z79hvw6L
这是 CLI 执行和 Valgrind 的输出(GDB 似乎没有提供任何更多信息):
请注意,CLI 给出了 malloc 内存损坏错误,而 Valgrind 没有。
CLI:http://pastebin.com/qdTKMCD2
VALGRIND:http://pastebin.com/8inRygnU
感谢您的帮助!
添加了 GDB Backtrace 结果
======= 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]
也许这可以让某人了解错误出现在程序的哪个部分?
I've tried using GDB and Valgrind, but I can't seem to pinpoint the problem.
Interestingly, the program crashes during normal execution and GDB, but not Valgrid.
To help you follow along with the code, heres the basic point of the program:
Communicate with a server via sockets and UDP to transfer a file, and handle some basic packet loss.
I won't share the server's code, because I know the issue isn't there.
The point that might confuse some, is that I'm implementing packet loss myself, with a number generator. Right now it doesn't do anything really, besides make the program use another recvfrom.
To guide you throught the programs output, the client tells the server what file it wants, the server tells the client how big the file is it's going to send, and then sends it in chunks (of 10 characters at a time).
The output shows what chunk is sent, how many characters were received, and what the concatenated string is.
The file transfer succeeds from what i can tell, its just the fopen call that I use to write the received file that is giving me trouble. Not sure if it's to do with my malloc call or not.
Here is the source code:
pastebin.com/Z79hvw6L
Here are the outputs from CLI execution, and Valgrind (GDB doesn't seem to give any more info):
Notice the CLI gives a malloc memory corruption error, and Valgrind doesn't.
CLI: http://pastebin.com/qdTKMCD2
VALGRIND: http://pastebin.com/8inRygnU
Thanks for any help!
Added the GDB Backtrace results
======= 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]
Maybe this could give someone an insight as to what part of the program the error is in?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是错误的, chunk[10] 是数组后面的一个。
一般来说,执行此操作时要小心,
如果输入长文件名,则会浪费内存。使用 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
code> ,但这也会减少 1,因为您为buf
分配了 10 个字节,并且您也尝试将 10 个字节读入其中 - 但在 C 中,字符串需要空间一个零终结者也是。将 buf 设置为 11 字节大。或者recv()只有9个字节。事实上,你已经偏离了很多地方,所以开始计算你需要多少字节,以及你是否在其中放入了东西。请记住,在 C 中,数组从索引 0 开始,而 10 的数组只能通过索引 0 到 9 进行索引。
is wrong, chunk[10] is one past the array.
And in general, be careful with doing this
If you enter a long filename, you'll trash memory. using fgets() would be better. You also would at least want to check if scanf succeeds, else the following strlen() on filename isn't valid.
line 93,
buf[strlen(buf)-1]='\0';
is dangerous, you can't use strlen if the buffer isn't already nul terminated, and you trash memory if buf is an empty string, as you index buf[-1].Edit.
Your other problem is
strcat(fullstring,chunk);
, you've no control in your loop that stops appending to this string if you happen to receive more data than it can hold. The size is also likely off by one, as you need room for the last nul terminator. Make it at leastchar * fullstring = malloc(sizeof(char)*filesize + 1 );
But your loop really needs to check that's it is not writing past the end of that buffer.As for adding a nul terminator to
buf
, the recv call returns how many bytes you've read, so if you've checked recv for errors, dobuf[numbytes] = 0
, but this will be off by one as well, as you've allocated 10 bytes forbuf
and you try to read 10 bytes into it as well - but in C, a string needs room for a nul terminator too. Make buf 11 bytes big. Or recv() only 9 bytes.In fact, you're off by one many places, so start counting how many bytes you need, and were you put stuff into them. Remember that in C, arrays starts with index zero, and an array of 10 can only be indexed by index 0 to 9.
这(第 93 行)是可疑的:
UPDATE 这(第 99,100 行)也是错误的:
UPDATE2:缓冲区太小
UPDATE3:
UDP 不可靠。数据包的传输可能会失败(数据包可能在发送方和接收方之间的任何位置被丢弃),并且数据包的接收顺序可能与发送顺序不同。
This (line 93) is suspect:
UPDATE This (line 99,100) is also wrong:
UPDATE2: The buffer is too small
UPDATE3:
UDP is unreliable. Transmission of a packet may fail (packets may be dropped anywhere between sender and receiver) , and the packets may be received in a different order than in which you sent them.
好吧,在现代操作系统上这不应该是问题:但您不会检查 malloc() 返回的值是否为 NULL。它在哪条线路上崩溃并发出什么信号?
Well, it shouldn't be a problem on modern OS:es but you don't check the returned value from malloc() for NULL. On what line does it crash and with what signal?