由于指针变量自身改变导致的 gcc 分段错误
gcc segmentation fault due to a pointer variable that changed itself
让我们考虑以下代码。
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);
}
main.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 设置为全局变量,它不会 change.When 我编译 运行 此代码 Ubuntu 18,gcc-7.5.0 Raspberry Pi (ARM),一切正常。它在 windows 上也能正常工作。那么这是 gcc 中的错误吗?
这是在ubuntu18(x86)+gcc-9.3.0上运行ning的结果
running on ubuntu18
这是 运行在 Raspberry Pi 上使用它的结果
run on raspberry pi
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
.
在任何地方都使用 long
,如果您的函数需要 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 位,使用 uint64_t
或 #include <stdint.h>
中的 int64_t
。参见 https://en.cppreference.com/w/c/types/integer。
free(NULL)
完全没问题 - 无需检查。
Do I cast the result of malloc?
让我们考虑以下代码。
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);
}
main.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 设置为全局变量,它不会 change.When 我编译 运行 此代码 Ubuntu 18,gcc-7.5.0 Raspberry Pi (ARM),一切正常。它在 windows 上也能正常工作。那么这是 gcc 中的错误吗?
这是在ubuntu18(x86)+gcc-9.3.0上运行ning的结果 running on ubuntu18
这是 运行在 Raspberry Pi 上使用它的结果 run on raspberry pi
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
.
在任何地方都使用 long
,如果您的函数需要 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 位,使用 uint64_t
或 #include <stdint.h>
中的 int64_t
。参见 https://en.cppreference.com/w/c/types/integer。
free(NULL)
完全没问题 - 无需检查。
Do I cast the result of malloc?