指向结构指针的空指针

void pointer to a struct pointer

我在将 void 指针分配给另一个结构指针时遇到问题。 我的输入参数在函数 semaphoreCreateBinary 中被更改,但是当它 returns 到 main 时它又是空的。我可能必须做一些铸造,但我似乎无法让它工作。

我将包括我认为理解我的问题所必需的代码:

来自我的头文件。

typedef struct semaphoreStruct
{
    int               smValue;  
    tcbExtS           *smHolder;  
    int               smCeiling;  
}semaS;

typedef void * SemaphoreHandle;

在我的 C 文件中

unsigned int semaphoreCreateBinary(void *ro_Handle,unsigned int i_InitialValue)
{
    semaS *Semaphorehandle1;

    Semaphorehandle = malloc (sizeof(*Semaphorehandle));

    Semaphorehandle1->smValue = i_InitialValue;
    ro_Handle = Semaphorehandle1; //seems to get the correct value

    return resultUnInt;
}

int main(void)
{
    SemaphoreHandle s1vPtr;

    semaphoreCreateBinary(&s1vPtr,0);

    int IV = s1vPtr->smValue//s1vPtr is empty again here
}

关于如何更正此问题的任何建议?

编辑: 即使我将参数作为地址传递: 信号量CreateBinary(&s1vPtr,0); 这是行不通的。 我无法更改输入类型,因为我们从老师那里得到的 API-Spec 否则我会更改它。

在您的代码中,在 semaphoreCreateBinary() 函数内

 ro_Handle = Semaphorehandle1;

不会达到你的目的。指针 ro_Handle 本身 通过按值传递传递给函数,因此您不能从函数更改指针本身并期望它在函数外部反映该更改.你可以改变指针指向的值,它会维持,但指针不会。

如果你想改变指针,你需要传递指针的地址,作为指针到指针。

话虽如此,

semaS *Semaphorehandle1;
Semaphorehandle1->smValue = i_InitialValue;

是完全错误的,因为此时 Semaphorehandle1 未初始化(即未指向任何有效的内存位置)并尝试取消引用未初始化的指针将导致 undefined behavior,导致分段故障。您需要先分配适当的内存,然后才能真正继续并取消引用该指针。

在 C 中,参数按值传递给函数。因此,您只更改函数内部的值。另外,还有一个错误:你没有分配Semaphorehandle1。所以,会有段错误。这将是正确的:

unsigned int semaphoreCreateBinary(void **ro_Handle,unsigned int i_InitialValue)
{
    semaS *Semaphorehandle1 = malloc(sizeof(semaS));
    Semaphorehandle1->smValue = i_InitialValue;
    *ro_Handle = Semaphorehandle; //seems to get the correct value
    return resultUnInt;
}

不要忘记在使用后释放内存。

在您的代码中,ro_Handle = Semaphorehandle1; 不会更改 main 范围内的指针值,因为指针是 semaphoreCreateBinary 范围内的副本(按值传递)。为了编辑指针的值,您需要一个指向它的指针:

unsigned int semaphoreCreateBinary(void **ro_Handle,unsigned int i_InitialValue) {
    ...
    *ro_Handle = Semaphorehandle1;

然后您需要将指针的地址传递给函数:

semaphoreCreateBinary(&s1vPtr,0);

看来你对指针的工作原理有一些严重的误解。指针是一个变量,可以存储有效变量的位置,但不是必须的——这取决于你是否正确地初始化了你的指针.你的线路

semaS *Semaphorehandle1;

声明一个未初始化指针,即指向任意内存位置的指针。下一行

Semaphorehandle1->smValue = i_InitialValue;

然后取消引用未初始化的指针,从而写入任意内存位置 - 这是典型的内存损坏,可能会导致整个程序出现未定义的行为。

这个有效:

unsigned int semaphoreCreateBinary(void *ro_Handle, unsigned int i_InitialValue)
{
    semaS *Semaphorehandle1 = malloc(sizeof(semaS));
    Semaphorehandle1->smValue = i_InitialValue;
    *(semaS**)ro_Handle = Semaphorehandle1;
}

int main(void)
{
    semaS* s1vPtr;
    semaphoreCreateBinary(&s1vPtr, 1);

    int IV = s1vPtr->smValue;

    free(s1vPtr);
    printf("%d\n", IV);
}

说明:要理解为什么这是对问题的有用解决方案,有两个重要的见解是必要的 - 作为未来的软件开发人员,您需要自己获得这些见解:

  1. 在 C 中,如果你想让一个函数修改某些东西,你必须传递一个指向那个东西的指针。在你的例子中,你想要修改一个 semaS* 指针(让它指向新的 malloced 内存位置)。所以如果你想修改一个semaS*,你必须传递一个semaS**给函数
  2. A void* 可以转换为任何指针类型,包括指针 指针。

另请注意,您的 malloc 初始尺寸有误。因为你想分配一个新的 semaS 结构,你必须 malloc 一个大小为 size(semaS) 的内存块(你 malloced 一个指针大小的内存块)。不幸的是,使用任何其他块大小不会在 C 中引发编译器警告或错误。但它会浪费内存(如果块大小太大)或导致内存损坏(如果块大小太小)。