【问题标题】:Allocating memory for char* attribute in C struct为 C 结构中的 char* 属性分配内存
【发布时间】:2015-10-05 01:08:57
【问题描述】:

假设我们在 C 文件中有以下结构定义:

typedef struct {
    char *name;
    int id;
    int last_cpu;
} thread_t;

(这是我正在编写的模拟,用于为我的操作系统类使用不同的调度算法)。每次我创建一个新的thread_t 结构时,我该如何处理其中一个变量是char* 的事实?例如,我的代码中有以下方法:

thread_t **get_starting_thread_list() {
    thread_t **threads = (thread_t **) malloc(MAX_NUM_THREADS * sizeof(thread *));
    int next_id = 0;

    for (int th_num = 0; th_num < MAX_NUM_THREADS; th_num++) {
        thread_t *new_thread = (thread_t *) malloc(sizeof(thread_t));
        new_thread->name = "New thread";
        new_thread->id = ++next_id;
        new_thread->last_cpu = 0;
        threads[th_num] = new_thread;
    }

    return threads;
}

如果new_threadname 字段“太大”,我可能会遇到分段错误吗?也就是说,我应该在分配线程名称之前为它分配额外的内存吗?我试过运行它,它似乎表现得很好,但我担心它以后可能会中断。

【问题讨论】:

  • 也不要在 C stackoverflow.com/a/605858/5339899 中转换 malloc 的值,你甚至不需要为 new_thread 分配内存
  • 为什么我不需要为threads分配内存?由于'threads 是此函数返回的内容,如果我不为其分配内存,难道不会出现段错误吗?
  • 注意:thread_t **threads = (thread_t **) malloc(MAX_NUM_THREADS * sizeof(thread *)); 的一个很好的简化是 thread_t **threads = malloc(sizeof *threads * MAX_NUM_THREADS);。更易于维护且代码错误的可能性更低。
  • 调用 malloc() 时不要强制转换返回值,因为返回值是void *,所以可以分配给任何指针。始终检查 (!=NULL) 返回值以确保操作成功。

标签: c struct segmentation-fault malloc


【解决方案1】:

如果new_thread 的名称字段“太大”,我可能会遇到分段错误吗?

不,无论字符串有多长,您都不会在此处出现段错误,因为字符串文字的内存是静态分配的,并且永远不会被复制。

也就是说,我应该在分配线程名称之前为其分配额外的内存吗?

除非您打算更改名称,否则不会。如果您想保持名称指向字符串文字,那么您的代码非常好。如果您想对名称使用非文字数据,请执行以下操作:

char buf[32];
sprintf(buf, "New thread %d", next_id);
new_thread->name = malloc(strlen(buf+1));
strcpy(new_thread->name, buf);

现在您需要在取消分配threads之前调用free(threads[i]-&gt;name)

我试过运行它,它似乎表现不错,但我担心它以后可能会中断。

您的代码很好。您始终可以使用内存分析器(例如 valgrind)来检查无效访问。

【讨论】:

  • “字符串文字的内存是静态分配的”是什么意思?
  • @Ryan 编译器将字符放在内存中的一个特殊段中,用于保存字符串文字。然后在运行时将此段加载到内存中,并为您的程序提供指向它的指针。
【解决方案2】:

在您的 sn-p 中,您将 name 指向文字字符串。如果您不打算更改它,那将永远正常工作。如果您想做ptr-&gt;name[0] = 'X'; 之类的操作,您现在正在尝试修改一个固定字符串,我认为这是未定义的行为(请观看语言律师确认或拒绝的 cmets ;-)。

【讨论】:

    【解决方案3】:

    在您的代码中,文字字符串“新线程”是静态分配的,而不是动态分配的。 (这意味着该文本在您的应用程序启动时就存在,而不是使用诸如malloc() 之类的函数从堆中动态分配。)因此这永远不会太大或导致段错误。该字符串位于静态内存中,现在您的 thread_t 结构将指向该内存。

    但是,在这种情况下,每个结构的值都相同。所以我怀疑这就是你的代码真正的样子。

    【讨论】:

      【解决方案4】:

      该结构定义了char *name;,无论它指向什么字符串,指针的大小都不会改变。

      所以这个问题的答案是:如果 new_thread 的 name 字段曾经“太大”,我是否可能会遇到分段错误? 是否,字符串的大小没有区别。

      但是,如果您定义了文字字符串,则该字符串无法更改。尝试更改文字字符串的内容将导致段错误事件。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-08-05
        • 2021-12-12
        • 2013-06-05
        • 1970-01-01
        • 1970-01-01
        • 2014-12-17
        • 2014-12-18
        相关资源
        最近更新 更多