2015-06-30 4 views
1

Я пытаюсь получить Mac адрес этого кода:Pass указатель голец функционировать в C

void getMacAdress(unsigned char **address) 
{ 
    int s; 
    struct ifreq buffer; 

    s = socket(PF_INET, SOCK_DGRAM, 0); 
    memset(&buffer, 0x00, sizeof(buffer)); 
    strcpy(buffer.ifr_name, "eth0"); 
    ioctl(s, SIOCGIFHWADDR, &buffer); 
    close(s); 
    *address = (unsigned char *)buffer.ifr_hwaddr.sa_data; 

    for (s = 0; s < 6; s++) 
    { 
     printf("%.2X ", *(*address + s)); 
    } 

    printf("\n"); 
} 

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

    getMacAdress(&address); 
    int i; 

    for (i = 0; i < 6; i++) 
    { 
     printf("%.2X ", *(address + i)); 
    } 

    printf("\n"); 
    return 0; 
} 

я получил правильный результат, как

08 00 27 0A 4E 98 
08 00 27 0A 4E 98 

, но при удалении printf сниппета кода в getMacAddress() функцию он становится:

void getMacAdress(unsigned char **address) 
{ 
    int s; 
    struct ifreq buffer; 

    s = socket(PF_INET, SOCK_DGRAM, 0); 
    memset(&buffer, 0x00, sizeof(buffer)); 
    strcpy(buffer.ifr_name, "eth0"); 
    ioctl(s, SIOCGIFHWADDR, &buffer); 
    close(s); 
    *address = (unsigned char *)buffer.ifr_hwaddr.sa_data; 
    printf("\n"); 
} 

Я получил неправильный результат

08 00 00 00 00 00 

Можете ли вы объяснить мне, почему это так и как я могу решить эту проблему?

+0

Почему вы передаете «указатель на указатель на символ»? – Olaf

+4

Я думаю, что указатель, который вы пишете в свой var, становится недействительным, как только вы выходите из функции, так как ваш буфер находится в стеке. –

+2

Вы копируете указатель на локальную переменную в 'getMacAdress()' в 'адрес', переданный в нее из' main() ', и это приводит к неопределенному поведению. Пространство повторно используется, и вы получаете то, что получаете (и вам повезло, что вы не потерпели крах). –

ответ

1

вы не можете указать на стеке, чтобы вернуться в функцию.

Вместо этого, вы можете таНос кучу пространства для хранения результата вы хотели:

void getMacAdress(unsigned char **address) 
{ 
    int s; 
    struct ifreq buffer; 

    s = socket(PF_INET, SOCK_DGRAM, 0); 
    memset(&buffer, 0x00, sizeof(buffer)); 
    strcpy(buffer.ifr_name, "eth0"); 
    ioctl(s, SIOCGIFHWADDR, &buffer); 
    close(s); 
    *address = (unsigned char*) malloc(sizeof(buffer.ifr_hwaddr.sa_data)); 
    memcpy(*address, buffer.ifr_hwaddr.sa_data,sizeof(buffer.ifr_hwaddr.sa_data)); 

    //for (s = 0; s < 6; s++) 
    //{ 
    // printf("%.2X ", *(*address + s)); 
    //} 

    //printf("\n"); 
} 

Кстати, не забудьте освободить пространство кучи в главной функции.

+0

Да, это хорошо работает, я понимаю, большое спасибо ... – Tiktac

3

Проблема здесь:

*address = (unsigned char *)buffer.ifr_hwaddr.sa_data; 

buffer является локальной переменной вашей функции. Таким образом, указатель, который вы храните в address, указывает на локальную переменную, которая уничтожается при возврате функции, оставляя свисающий указатель.

Пытаться прочитать этот указатель вызывает неопределенное поведение. Ваш результат можно объяснить в зависимости от того, была ли память повторно использована для чего-то еще уже к тому времени, когда вы сделали печать или нет.

+0

Да, я понимаю, но почему добавление функции printf в getMacAdress() приводит к получению истинного результата? – Tiktac

+0

@Sam Отключение локального указателя за пределами области видимости - это неопределенное поведение, что означает, что все может произойти. Вызов printf просто происходит, чтобы вызвать некоторые закулисные шарлатанства, которые изменили характер неопределенного поведения. – ApproachingDarknessFish

+0

Это просто удача. Случайно старые данные не были перезаписаны путём стека. Ваша память, на которую указывает «адрес», была немного неопределенной. Он был создан, чтобы быть освобожденным, но ничего не перезаписано, потому что не так много использовали стек. – jaybers

2

Если вы хотите, чтобы исправить это ...

//*address = (unsigned char *)buffer.ifr_hwaddr.sa_data; 
*address = malloc (strlen (buffer.ifr_hwaddr.sa_data) + 1); 
strcpy (*address, buffer.ifr_hwaddr.sa_data); 
Смежные вопросы