简体   繁体   English

C结构值未分配

[英]C Struct values not being assigned

I'm trying to use the Video4Linux2 API , but something peculiar is happening with the structs that I'm supposed to use to change the various controls on a given camera. 我正在尝试使用Video4Linux2 API ,但是我用来更改给定摄像机的各种控件的结构正在发生一些奇怪的事情。 For some reason, some of the members aren't reporting back as changed on assignment. 由于某些原因,有些成员没有报告分配的变更。 I wrote the following code to simplify the problem: 我编写了以下代码来简化问题:

#include <getopt.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/select.h>
#include <linux/videodev2.h>
#include <stdlib.h>
#include <errno.h>
#include <stdbool.h>

int setExtendedControl(int id, int value);
int fd = 0;

int main()
{
    setExtendedControl(20, 30);
    return 0;
}

int setExtendedControl(int id, int value)
{
    struct v4l2_ext_control extControl;
    struct v4l2_ext_controls extControls;

    extControl.id = id;
    extControl.value = value;
    extControl.value64 = value;
    extControl.reserved2[0] = 0;
    extControl.reserved2[1] = 0;
    extControl.reserved2[2] = 0;

    //Put the individual control structure into the
    //multi-control container structure and initialize the container
    //as well
    extControls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
    extControls.count = 1;
    extControls.controls = &extControl;
    printf("extControls.controls = %i, extControl = %i\n", (extControls).controls, &extControl);



    extControls.reserved[0] = 0;
    extControls.reserved[1] = 0;
    extControls.reserved[2] = 0;
    extControls.error_idx = 0;

    printf("Verifying settings:\n");
    printf("extControl.id = %i, id = %i\n", extControl.id, id);
    printf("extControl.value = %i, value = %i\n", extControl.value, value);
    printf("extControl.value64 = %i, value = %i\n", extControl.value64, value);
    printf("extControl.reserved2[0] = %i, set to 0\n", extControl.reserved2[0]);
    printf("extControl.reserved2[1] = %i, set to 0\n", extControl.reserved2[1]);
    printf("extControl.reserved2[2] = %i, set to 0\n\n", extControl.reserved2[2]);

    printf("extControls.ctrl_class = %i, V4L2_CTRL_CLASS_MPEG = %i\n", extControls.ctrl_class,
            V4L2_CTRL_CLASS_MPEG);
    printf("extControls.count = %i, set to 1\n", extControls.count);
    printf("extControls.reserved[0] = %i, set to 0\n", extControls.reserved[0]);
    printf("extControls.reserved[1] = %i, set to 0\n", extControls.reserved[1]);
    printf("extControls.reserved[2] = %i, set to 0\n", extControls.reserved[2]);
    printf("extControls.error_idx = %i, set to 0\n", extControls.error_idx);

    printf ("\nRunning secondary check..\n\n");


    int rval;

    //Set up the individual control structure



    //Try to change the control and return the
    //value reporting the outcome.
    rval = ioctl(fd, VIDIOC_S_EXT_CTRLS, &extControls);

    if (extControls.controls != &extControl)
    {
        printf("\n\nLost the pointer on initial set!\n");
    }
    //printf("error_idx after initial set %i\n", extControls.error_idx);

    //printf("extControl = %i, extControls = %i\n");

    //freeStructs(extControl, extControls);

    return rval;
}

When I run this, the "value" and "value64" members aren't set. 运行此命令时,未设置“ value”和“ value64”成员。 The following is the printf outputs: 以下是printf的输出:

extControls.controls = -1954893344, extControl = -1954893344
Verifying settings:
extControl.id = 20, id = 20
extControl.value = 0, value = 30
extControl.value64 = 0, value = 30
extControl.reserved2[0] = 0, set to 0
extControl.reserved2[1] = 0, set to 0
extControl.reserved2[2] = 0, set to 0

extControls.ctrl_class = 10027008, V4L2_CTRL_CLASS_MPEG = 10027008
extControls.count = 1, set to 1
extControls.reserved[0] = 0, set to 0
extControls.reserved[1] = 0, set to 0
extControls.reserved[2] = 0, set to 0
extControls.error_idx = 0, set to 0

And here is a small snippet from gdb: 这是gdb的一小段代码:

(gdb) step
printf (__fmt=0x400880 "extControls.controls = %i, extControl = %i\n") at /usr/include/x86_64-linux-gnu/bits/stdio2.h:105
105       return __printf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __va_arg_pack ());
(gdb) step
setExtendedControl (id=20, value=30) at ioctlTest.c:30
30          extControl.reserved2[0] = 0;
(gdb) step
Hardware watchpoint 2: extControl

Old value =
    {id = 4294960502, size = 32767, reserved2 = {4196309}, {value = 0, value64 = 67750802696962048, string = 0xf0b2ff00000000 <Address 0xf0b2ff00000000 out of bounds>}}
New value =
    {id = 20, size = 32767, reserved2 = {0}, {value = 0, value64 = 67750802696962048, string = 0xf0b2ff00000000 <Address 0xf0b2ff00000000 out of bounds>}}

It's not happening here, but there have been other instances in a beefier version of this code where the pointer assignment for extControls.controls and int assignment of member extControl.id both fail. 这里没有发生这种情况,但是在此代码的更强大的版本中还有其他实例,其中extControls.controls的指针分配和成员extControl.id的int分配均失败。 What would cause a struct member assignment failure of this nature? 是什么会导致这种性质的结构成员分配失败?

Thanks in advance! 提前致谢!

See kernel docs for struct information 请参阅内核文档以获取结构信息

The reserved[] array for the v4l2_ext_control struct is only of length 2...so you're modifying memory that you shouldn't be with the line: v4l2_ext_control结构的reserved[]数组的长度仅为2 ...因此您要修改的内存不应该与该行一起使用:

extControl.reserved2[2] = 0;

Can't check this myself, but looking at this spec of struct v4l2_ext_control (Table 1), it says: 我自己无法检查,但是查看struct v4l2_ext_control规格 (表1),它说:

Table 1. struct v4l2_ext_control 表1. struct v4l2_ext_control

__u32   id      Identifies the control, set by the application.
__u32   reserved2[2]        Reserved for future extensions. Drivers and applications must set the array to zero.

union   (anonymous)      
    __s32   value       New value or current value.
    __s64   value64     New value or current value.
    void *  reserved    Reserved for future pointer-type controls. Currently unused.

Note three things here: 请注意此处的三件事:

  • value and value64 are part of a union, they occupy the same location in memory valuevalue64是联合的一部分,它们在内存中占据相同的位置
  • reserved2 has size two, so only, reserved2[0] , reserved2[1] , no reserved2[2] ! reserved2的大小为2,因此,只有reserved2[0]reserved2[1] ,没有reserved2[2]
  • according to this spec, reserved memory address precedes the union within the struct 根据此规范, reserved内存地址在结构内的联合之前

This means that when you set 这意味着当您设置

extControl.reserved2[2] = 0;

you are actually writing outside the memory assigned to that array, overwriting the data of the union, thus altering "both" value and value64 members at the same time. 您实际上是在分配给该数组的内存外部进行写操作,覆盖并的数据,从而同时更改了valuevalue64成员。

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

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