Home > other >  Why do I have a segmentation error sometime?
Why do I have a segmentation error sometime?

Time:06-17

I have a segmentation error in the second_get_device_descriptor function, with this line:

ret = libusb_get_device_descriptor(dev, &device_descriptor);

while the same line in the first function work perfectly. Here is my code:

#include <stdio.h>
#include <stdlib.h>
#include <libusb-1.0/libusb.h>


void first_get_device_descriptor(libusb_device ** devices, libusb_device * dev){
    struct libusb_device_descriptor device_descriptor;
    dev = devices[10];
    int ret;
    ret = libusb_get_device_descriptor(dev, &device_descriptor);
}

void second_get_device_descriptor(libusb_device *dev){
    struct libusb_device_descriptor device_descriptor;
    int ret;
    ret = libusb_get_device_descriptor(dev, &device_descriptor);
}



int main(int argc, char* argv[]) {

    libusb_device **devices;
    libusb_device *dev;
    libusb_context *context = NULL;

    libusb_init(&context);
    libusb_get_device_list(context, &devices);

    
    first_get_device_descriptor(devices, dev);

    //Android device found

    second_get_device_descriptor(dev);


    libusb_free_device_list(devices, 1);
    libusb_exit(context);
    return 0;
}

Anyone have an idea with this please?

CodePudding user response:

In your first function, you assigned dev a value. In the 2nd you didn't. libusb_get_device_descriptor will dereference this uninitialized variable and your program will have undefined behavior as a result.

CodePudding user response:

dev = devices[10];

discards the (thoroughly useless due to being uninitialized) pointer passed to you from the caller, so you neither use the caller's pointer, nor what it points to, nor do they have any access to what you changed it to (unless they also reference devices[10]). Thus, the caller's dev remains an uninitialized pointer.

The second_get_device_descriptor also receives that original uninitialized dev, does not initialize it to anything, and passes it to libusb_get_device_descriptor, that could only possibly do something useful if dev pointed to valid allocated memory, which it does not. Presumably libusb_get_device_descriptor tries to dereference that pointer at some point (to read or write it), it still points to garbage, and you seg fault.

What you wanted to do I can't say (I don't know these APIs), but odds are you should be receiving dev as a double pointer (if the function(s) are responsible for allocating the memory, so you can change the caller's pointer through the double-pointer), or it needs to be allocated by the caller so the functions called with it can use it without reallocating/reassigning it.

CodePudding user response:

    libusb_device *dev; /* dev is uninitialized here */

    /* you're passing the still-uninitialized pointer by value here */
    first_get_device_descriptor(devices, dev);

    /* you still haven't initialized dev! */
    second_get_device_descriptor(dev);

When you write a function like

void first_get_device_descriptor(libusb_device ** devices, libusb_device * dev)
{
    dev = /*something*/

it doesn't change the caller's dev, it only alters the local variable dev inside the scope of this function. Don't be confused by the fact they happen to have the same name. After all, if you called first_get_device_descriptor(devices, NULL), it wouldn't change the value of NULL, would it?

You can - and really should - verify this by using a debugger or adding some print statements to your code.

Finally, there are two actual solutions:

  1. use dev as an out-parameter here, which in C means passing a pointer (to a pointer):

    void first_get_device_descriptor(libusb_device **devices, libusb_device **dev)
    {
        *dev = /*something*/
    }
    /* called like */
    first_get_device_descriptor(devices, &dev);
    
  2. or just return dev:

    libusb_device* first_get_device_descriptor(libusb_device **devices)
    {
        libusb_device *dev = /* something */
    
        ...
    
        return dev;
    }
    /* called like */
    dev = first_get_device_descriptor(devices);
    
  • Related