【问题标题】:gcc segmentation fault due to a pointer variable that changed itself由于指针变量自行更改导致 gcc 分段错误
【发布时间】:2026-02-22 02:25:02
【问题描述】:

让我们考虑以下代码。

message_word.h

struct array_int64{
        int size;
        long* value;
};
struct array_int64* array_int64_create(int size);
int array_int64_get(void* value, const struct array_int64* array, int index);
int array_int64_set(struct array_int64* array, long value, int index);
void array_int64_free(struct array_int64* array);
struct hello_message{
        struct array_int64* test;
};
struct hello_message* hello_message_create();
void hello_message_free(struct hello_message* msg);

message_word.c

#include <stdlib.h>
#include <string.h>
#include "word_message.h"

struct array_int64* array_int64_create(int size){
        struct array_int64* new_array = (struct array_int64*)malloc(sizeof(struct array_int64));
        new_array->size = size;
        new_array->value = (long*)malloc(sizeof(long) * (new_array->size));
        return new_array;
}
int array_int64_get(void* value, const struct array_int64* array, int index){
        long* vvalue = (long*)value;
        if(index >= array->size)
                return -1;
        *vvalue = (array->value)[index];
        return 0;
}
int array_int64_set(struct array_int64* array, long value, int index){
        if(index >= array->size)
                return -1;
        array->value[index] = value;
        return 0;
}
void array_int64_free(struct array_int64* array){
        if(array != NULL && array->value != NULL)
                free(array->value);
        if(array != NULL)
                free(array);
}
struct hello_message* hello_message_create(){
        struct hello_message* new_msg = (struct hello_message*)malloc(sizeof(struct hello_message));
        new_msg->test = array_int64_create(5);
        return new_msg;
}
void hello_message_free(struct hello_message* msg){
        if(msg == NULL) return;
        array_int64_free(msg->test);
        free(msg);
}

ma​​in.c

#include "word_message.h"
#include <stdio.h>

//struct hello_message* msg = NULL;

int main(void)
{
        struct hello_message* msg = hello_message_create();
        //msg = hello_message_create();
        array_int64_set(msg->test, 10, 0);
        int number;
        array_int64_get(&number, msg->test, 0);
        printf("value is: %d\n", number);
        array_int64_get(&number, msg->test, 0);
        printf("value is: %d\n", number);
        hello_message_free(msg);
        return 0;
}

当我在 Ubuntu 上使用 gcc-9.3.0 或 gcc-7.5.0 编译和运行此代码时,执行 array_int64_get 时,msg 引用地址会自行改变。但是,如果您像注释中那样将 msg 设为全局变量,它不会改变。当我在 Ubuntu 18 上编译并运行此代码时,在 Raspberry Pi (ARM) 上的 gcc-7.5.0 上,一切正常。它在 Windows 上也可以正常工作。那么这是 gcc 中的错误吗?

这是在ubuntu18(x86)+gcc-9.3.0上运行的结果 running on ubuntu18

这是在树莓派上运行的结果 run on raspberry pi

【问题讨论】:

  • 您正在获取int 的地址并将其转换为long*。这似乎不对。
  • int number; array_int64_get(&amp;number, msg-&gt;test, 0); 不正确。如果您要将number 视为函数内部的long,它也应该是函数外部的一个。您可以考虑改用int64_t。您的代码可以在 Windows 中运行,因为 intlong 大小相同,而且都不是 64 位。
  • 顺便说一句,为什么要设置为需要很长时间,然后让 get 使用 void*,而不是 long*?这将减少此类错误的可能性。
  • 对不起,我以为这个问题会出现在 C 或 C++ 中,所以我将其标记为 C++,但当然这是一段 C 代码
  • @RetiredNinja 真诚地感谢您的回答。我认为这是根本原因。

标签: c gcc


【解决方案1】:
int array_int64_get(void* value, const struct array_int64* array, int index){
        long* vvalue = (long*)value;
        ...
 }

 int main() {
        int number;
        array_int64_get(&number, msg->test, 0);
 }

您正在传递带有指针的int,然后将其读取为long。那是无效的。如果你想要long,那就是long

在任何地方都使用longs,如果您的函数需要long,请使用long

int array_int64_get(long *vvalue, const struct array_int64* array, int index){
    ...
}

 int main() {
        int number;
        array_int64_get(&number, ...); // compiler warning!
        long correctnumber;
        array_int64_get(&correctnumber, ...); // all fine!
 }

从概念上讲,您的代码很奇怪。 long 不是 64 位长,它是至少 32 位长。它可以有 32 位、64 位、1000 位。对于 64 位,使用来自 #include &lt;stdint.h&gt;uint64_tint64_t。见https://en.cppreference.com/w/c/types/integer

free(NULL) 完全没问题 - 无需检查。

Do I cast the result of malloc?

【讨论】:

    最近更新 更多