You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何将int8_t数组追加至更大数组?UDP流读取JPG分片咨询

Appending uint8_t Arrays & Optimizing UDP JPG Fragment Reception

Hey there, let's break down your question about appending uint8_t arrays (functionally identical to int8_t for byte-wise operations) and evaluate your current UDP JPG receiver code.

Is Your Current memcpy Approach Reasonable?

Short answer: Yes, it's absolutely reasonable and efficient. Here's why:

  • memcpy is the standard C library function for block memory copies, and compilers almost always optimize it to use hardware-specific instructions (like rep movsb on x86) for maximum speed.
  • Since you're working with single-byte values (uint8_t), there's no extra overhead—memcpy directly copies bytes exactly as needed, and the logic is straightforward to read and maintain.

That said, your code has a few potential pitfalls to address:

  • Fixed-size buffer risk: The jpg[BUF_SIZ * 256] array uses a hardcoded maximum size. If you receive more than 256 fragments, you'll get a buffer overflow. If you receive fewer, you're wasting memory.
  • UDP unreliability: UDP doesn't guarantee packet order or delivery. Your code assumes packets arrive in order and never get lost—this will break the JPG file if either assumption fails.
  • Missing bounds checks: You don't verify that ptr + (numbytes - 46) stays within the jpg array's limits, which could lead to undefined behavior if the math is off.

Better Implementation Options

Let's go through actionable improvements for your use case:

1. Dynamic Memory Allocation (Avoid Fixed Buffers)

Use malloc and realloc to grow the jpg buffer as needed, so you only use as much memory as required and avoid overflow:

#include <stdlib.h>
#include <stdint.h>

#define BUF_SIZ 1066
int main(int argc, char *argv[]) {
    size_t ptr = 0;
    size_t jpg_capacity = BUF_SIZ * 32; // Start with enough space for 32 fragments
    uint8_t *jpg = malloc(jpg_capacity);
    if (!jpg) {
        // Handle memory allocation failure (log error, exit)
        return 1;
    }
    uint8_t buf[BUF_SIZ];

repeat:
    // ... Check for first packet, populate buf with UDP data
    size_t data_len = numbytes - 46;

    // Resize buffer if needed (double capacity each time to minimize realloc calls)
    if (ptr + data_len > jpg_capacity) {
        jpg_capacity *= 2;
        uint8_t *temp_buf = realloc(jpg, jpg_capacity);
        if (!temp_buf) {
            // Handle resize failure (clean up existing memory)
            free(jpg);
            return 1;
        }
        jpg = temp_buf;
    }

    // Append the fragment data
    memcpy(&jpg[ptr], &buf[46], data_len);
    ptr += data_len;

    // ... Check if this is the last packet; if not, goto repeat

ending:
    // Process the complete JPG data
    // ...

    // Clean up dynamically allocated memory
    free(jpg);
    return 0;
}

2. Handle UDP's Unreliability

UDP packets can arrive out of order or go missing. To fix this, add fragment metadata to each UDP packet header (work with your sender to implement this):

  • Include a total fragment count and current fragment number in the 46-byte header.
  • Track which fragments you've received, and only assemble the JPG once all fragments are present (or request retransmissions for missing ones).

Example snippet for ordered assembly:

// Assume header bytes 0-3 = total fragments (uint32_t), bytes 4-7 = current fragment number
uint32_t total_frags = *(uint32_t *)&buf[0];
uint32_t curr_frag = *(uint32_t *)&buf[4];
size_t frag_data_len = numbytes - 46;

// Allocate buffer for full JPG (if we know total size upfront)
uint8_t *jpg = malloc(total_frags * frag_data_len);
int received_frags[total_frags] = {0}; // Track received fragments

// Copy fragment to its correct position (not just append)
memcpy(&jpg[(curr_frag - 1) * frag_data_len], &buf[46], frag_data_len);
received_frags[curr_frag - 1] = 1;

// Check if all fragments are received
int all_received = 1;
for (int i = 0; i < total_frags; i++) {
    if (!received_frags[i]) {
        all_received = 0;
        break;
    }
}
if (all_received) {
    goto ending;
}

3. Minor Optimizations (Optional)

  • If you ever have overlapping memory regions (you don't here), use memmove instead of memcpy—but for your append use case, memcpy is faster.
  • Avoid manual byte loops for copying—memcpy will always outperform handwritten loops because of compiler optimizations.

Final Takeaways

  • Your core memcpy approach to appending arrays is solid—it's the standard, efficient way to handle this in C.
  • The biggest improvements you can make are adding dynamic memory management to avoid buffer issues and handling UDP's unreliability to ensure the JPG is assembled correctly.

内容的提问来源于stack exchange,提问作者John Smith

火山引擎 最新活动