You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言TCP Socket简易Torrent客户端内存损坏问题排查求助

Troubleshooting Random Memory Issues in a TCP Socket-Based Torrent Client

Hey there, sorry to hear you're stuck with those frustrating random memory crashes in your torrent client—those are always the trickiest bugs to track down. You already fixed the malloc off-by-one bug with aux, so let's dig into other potential culprits in your code and workflow:

1. Uninitialized Memory & Buffer Overflows in Block Handling

Looking at your block receiving code:

ssize_t recv_payload = recv(socket_client,&bloque_rebut,mida,0);

If your block_t struct includes a pointer field (like data to store the actual block content), you're directly writing raw network data into the struct itself—not into allocated memory for that pointer. This will almost certainly overwrite adjacent memory or corrupt the heap, leading to unpredictable crashes.

Fix this by explicitly allocating memory for the block data before receiving:

// After getting `mida` from get_block_size
bloque_rebut.data = malloc(mida);
if (!bloque_rebut.data) {
    perror("Failed to allocate memory for block data");
    exit(EXIT_FAILURE);
}
// Now receive into the allocated buffer (use the recv_all helper below)
ssize_t recv_payload = recv_all(socket_client, bloque_rebut.data, mida);
// Don't forget to free bloque_rebut.data after storing the block!

Also, if mida is large (e.g., multi-megabyte blocks), storing this struct on the stack could trigger stack overflow—heap allocation is safer here.

2. TCP Stream Mismanagement (Sticky/Partial Packets)

TCP is a stream protocol, not a message-based one. Your current code assumes that the first recv gets exactly the message header, and the second gets exactly the full payload—but that's not guaranteed. You might get partial reads, or even multiple messages stuck together (粘包), which will corrupt your block data and cause memory errors when parsing.

Fix this by writing a helper function to guarantee full reception of a specified number of bytes:

ssize_t recv_all(int sock, void *buf, size_t len) {
    size_t total_received = 0;
    while (total_received < len) {
        ssize_t bytes = recv(sock, (char*)buf + total_received, len - total_received, 0);
        if (bytes <= 0) {
            // Error or connection closed unexpectedly
            return bytes;
        }
        total_received += bytes;
    }
    return total_received;
}

Use this function for all your recv calls to ensure you get exactly the data you need, no more no less.

3. Byte Order & Peer Address Handling

Your manual byte-shifting for the peer IP address is error-prone:

uint32_t direccion=0x0;
direccion |= ((uint32_t) Torrent_Client.peers[peer_count].peer_address[3]);
direccion = direccion << 8;
direccion |= ((uint32_t) Torrent_Client.peers[peer_count].peer_address[2]);
// ... and so on

If peer_address is stored in network byte order (big-endian, standard for torrent protocols), your manual shift will convert it to host byte order—but client_addr.sin_addr.s_addr expects a network byte order value. This could lead you to connect to an invalid IP, receive garbage data, and trigger random memory corruption.

Replace this with standard byte-order functions to avoid mistakes:

// Assuming peer_address is a 4-byte array in network order
client_addr.sin_addr.s_addr = *((uint32_t*)Torrent_Client.peers[peer_count].peer_address);

4. Unchecked Array Access & Peer Validation

You're accessing Torrent_Client.peers[peer_count] without verifying that peer_count is within the bounds of the peers array. If peer_count is larger than the actual number of peers (or if peers is uninitialized), this will read out-of-bounds memory, leading to undefined behavior (random crashes included).

Add a check before accessing the peer:

if (peer_count >= Torrent_Client.peer_total) {
    perror("Peer index out of bounds");
    exit(EXIT_FAILURE);
}

Make sure Torrent_Client.peer_total is properly set by create_torrent_from_metainfo_file.

5. Debugging Tools to Pinpoint the Exact Issue

Random memory bugs are hard to spot with just code inspection—use these tools to get concrete data:

  • Valgrind: Run your program with valgrind --leak-check=full --track-origins=yes ./your_client your_torrent.torrent. It will flag uninitialized memory access, buffer overflows, and memory leaks with exact line numbers.
  • GDB: If your program crashes, use gdb ./your_client core to load the crash dump. Run bt to get a backtrace of where the crash happened. You can also set watchpoints on suspicious variables to catch when they're modified unexpectedly.

内容的提问来源于stack exchange,提问作者Desiree Pasion Rodriguez Sanch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 14:17:43