简体   繁体   English

从struct **初始化struct-segfault

[英]Initializing struct from struct** - segfault

I'm trying to initialize a struct, from a pointer, to a pointer. 我正在尝试初始化一个结构,从一个指针到一个指针。 I'm doing this with an init function. 我正在使用init函数。 This, however gives a segfault. 但是,这会造成段错误。 The pointer i'm trying to initialize from, is defined within an array. 我试图从中初始化的指针是在数组中定义的。 When the size of the array is set to 1, the segfault does not occur. 当数组的大小设置为1时,不会发生段错误。

typedef struct{
  int a;
}myStruct;

void init_struct(myStruct** s){
  (*s)->a=10;
}

void fun(myStruct** sp){
  init_struct(sp);
}

int main(){
  myStruct* s[2];
  fun(&s[0]);
}

I know this is because I'm accessing memory I'm not supposed to, but why am i not allowed in this case? 我知道这是因为我不应该访问内存,但是为什么在这种情况下我不允许访问? Why is this ok when the size of the array is 1? 当数组的大小为1时为什么可以? (I'm assuming undefined behavior) (我假设行为不确定)

This is a simplified part of a school assignment, so i'm not allowed to alter the contents of 'main'. 这是学校作业的简化部分,因此不允许我更改“主要”的内容。

With myStruct* s[2] , you reserve memory for two pointers to myStruct , but you do not initialize these pointers in order to let them point to valid myStruct -objects. 使用myStruct* s[2] ,您可以为两个指向myStruct指针保留内存,但是不初始化这些指针是为了使它们指向有效的myStruct对象。 Dereferencing such an (uninitialized) pointer then yields undefined behaviour (very likely a segfault). 然后,取消引用此类(未初始化的)指针会产生未定义的行为(很有可能发生段错误)。

A command like 像这样的命令

s[0] = malloc(sizeof(myStruct));

should solve this at least for the first pointer. 应该至少针对第一个指针解决此问题。

If you cannot alter the contents of 'main'. 如果您不能更改“ main”的内容。 You can try 你可以试试

void init_struct(myStruct** s) {
    (*s) = malloc(sizeof(myStruct));
    (*s)->a=10
}

the posted code fails to actually allocate any memory for the actual struct instance. 发布的代码无法实际为实际的struct实例分配任何内存。

So trying to write where the pointer points is writing to memory that the application does not own 因此,尝试编写指针指向的位置正在写入应用程序不拥有的内存

Note that myStruct * s[2] simply declares an array of 2 unititialized pointers (to structs of the myStruct type). 请注意, myStruct * s[2]只是声明了一个由2个单位初始化的指针组成的数组(指向myStruct类型的结构)。

The pointers may very well point to invalid memory, which you are accessing in init_struct by the following expression: (*s)->a (which, in case you didn't already know, is equivalent to s[0]-> ). 指针很可能指向无效的内存,您可以通过以下表达式在init_struct进行访问: (*s)->a (如果您还不知道,它等效于s[0]-> ) 。

You could fix the invalid memory access, by allocating the memory required to fit the structure: 您可以通过分配适合该结构的内存来修复无效的内存访问:

s[0] = malloc(sizeof s[0]);

You should also check if malloc succeeded allocating the memory: 您还应该检查malloc成功分配了内存:

if (s[0] == NULL) {
    return; // error
}

Then you may freely write to the uninitialized members of the myStruct you just allocated: 然后,您可以自由地写入刚分配的myStruct的未初始化成员:

s[0]->a = 10;

Note that your application will have a memory leak, unless you also free the allocated memory: 请注意,除非您还释放分配的内存,否则应用程序将发生内存泄漏:

free(s[0]);

Furthermore, you may check for errors using the very useful tool valgrind which should give you the following output: 此外,您可以使用非常有用的工具valgrind检查错误,该工具应该为您提供以下输出:

$ valgrind ./a.out
==12820== Memcheck, a memory error detector
==12820== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==12820== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==12820== Command: ./a.out
==12820== 
==12820== 
==12820== HEAP SUMMARY:
==12820==     in use at exit: 0 bytes in 0 blocks
==12820==   total heap usage: 1 allocs, 1 frees, 8 bytes allocated
==12820== 
==12820== All heap blocks were freed -- no leaks are possible
==12820== 
==12820== For counts of detected and suppressed errors, rerun with: -v
==12820== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

There are several things wrong with the original code: 原始代码有几处错误:

  1. It never actually initializes any storage (the main problem) 它实际上从未初始化任何存储(主要问题)

  2. It's hard-coded to "2 elements" 它被硬编码为“ 2个元素”

  3. "fun()" appears more or less irrelevant “ fun()”或多或少无关紧要

  4. If you have an "allocate" function, you might also want a corresponding "free" 如果您具有“分配”功能,则可能还需要相应的“免费”

SUGGESTED CHANGES: 建议更改:

#include <stdio.h>
#include <malloc.h>

typedef struct myStruct {
  int a;
} myStruct_t;

myStruct_t** init_struct_array(int nelms){
  int i;
  myStruct_t **sArray = malloc(sizeof (myStruct_t*)*nelms);
  for (i=0; i < nelms; i++) {
    sArray[i] = malloc(sizeof (myStruct_t));
    sArray[i]->a = i;
    /* Any other initialization you might want goes here... */
  }
  return sArray;
}

void free_struct_array(myStruct_t **sArray, int nelms){
  int i;
  for (i=0; i < nelms; i++) {
    free(sArray[i]);
  }
  free(sArray);
}

int main(){
  int i, n = 2;
  myStruct_t** s = init_struct_array(n);
  /* Use your array here... */
  for (i=0; i < n; i++) 
    printf ("s[%d]->a=%d...\n", i, s[i]->a);
  free_struct_array(s, n);
}

You probably also want to put your "typedef", along with prototypes for "init_struct_array()", "free_struct_array", and any other related "operations" in their own .h header file. 您可能还希望将“ typedef”以及“ init_struct_array()”,“ free_struct_array”以及所有其他相关“操作”的原型放到自己的.h头文件中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM