通过引用传递结构与在 malloc 之后传递

Passing struct by reference vs after malloc

这两种方法在数据可见性和内存开销方面有何区别(任何其他差异也会很大):

  1. 通过引用传递本地结构
  2. 传递指向已分配内存的指针
typedef struct student_data_t_ {
    char name[30];
    int score;
} student_data_t;

void fill_values (student_data_t *data) {
    snprintf(data->name, 30, "Howard");
    data->score = 20;
    return;
}

int main (void) {
    student_data_t record;
    student_data_t *ptr = NULL;

    fill_values(&record); // <1> passing the struct by reference

    ptr = (student_data_t *)malloc(sizeof(student_data_t));
    if (!ptr) {
        printf("NOMEM");
        return 0;
    }

    fill_values(ptr);  // <2> passing after allocating memory

    if (ptr) {
        free(ptr);
    }

    return 0;
}

对于局部变量,内存开销将完全存在于该线程的堆栈中。如果你在嵌入式系统中使用大型结构,这可能会成为一个问题,因为你有堆栈溢出的风险。通常您只会使用请求的字节数,但堆栈 space 可能会受到限制。 (我工作的一些应用程序有 512 字节或更少的堆栈)

在使用 malloc 的情况下,您是从堆中分配内存。这避免了堆栈大小问题,但增加了在完成后释放内存的要求。

可见性由存储指针的变量决定。

将局部变量传递给单独的线程是非常危险的,如果局部变量无效(例如由于函数返回),可能会导致未定义的行为。

传递一个本地结构肯定会更快,程序可以在编译时做一些奇怪的事情。从机器代码的角度来看,局部结构实际上是一个常量内存地址。 当你开始使用 malloc 时,必然会有处理开销,还有一个 space 问题。尽管这两个结构是相同的,但 malloc 可能 "use" 比 sizeof(struct) 存储数据更多的内存。 malloc 还在每个页面上保留 space 以维护和内存地址大小分配的内存查找 table,这允许 free 只需要一个地址作为参数。

最大的问题之一是开发时间引入 malloc 和 free to programs 增加了出现错误的机会,尤其是分段错误。更不用说难以追踪 "invisible " 内存泄漏错误。 但是使用 malloc 和 calloc 是处理用户输入的唯一方法,你永远不知道他们要输入多少数据,一个 2kb 的文本输入缓冲区很容易被 fgets

的调用填满